Compare commits

...

23 Commits

Author SHA1 Message Date
Mark Paluch
70f77bfd1f DATAES-496 - Release version 3.1.3 (Lovelace SR3). 2018-11-27 13:43:25 +01:00
Mark Paluch
d887b1bc9b DATAES-496 - Prepare 3.1.3 (Lovelace SR3). 2018-11-27 13:42:18 +01:00
Mark Paluch
6636bbb364 DATAES-496 - Updated changelog. 2018-11-27 13:42:16 +01:00
Mark Paluch
b116cce1e8 DATAES-490 - Updated changelog. 2018-11-27 12:36:51 +01:00
Mark Paluch
ed7a761912 DATAES-491 - Updated changelog. 2018-11-27 11:27:26 +01:00
tsallase
b0353ec4e5 DATAES-445 - Updated scroll API example.
Original pull request: #218
2018-11-20 11:52:36 +01:00
xhaggi
758e697aec DATAES-33 - Polishing
* Move @Parent property recognition to ElasticsearchPersistentProperty
* Move type contraints for @Version and @Parent fields to ElasticsearchPersistentProperty to fail faster
* remove unused constant SUPPORTED_ID_TYPES from SimpleElasticsearchPersistentProperty

Original pull request: #208
2018-11-20 11:48:01 +01:00
xhaggi
02761a48e0 DATAES-503 - Added missing copy_to property to @Field annotation.
Original pull request: #227
2018-11-20 11:25:31 +01:00
xhaggi
e6fbc37550 DATAES-492 - Add missing normalizer property to @Field and @InnerField.
Original pull request: #222
2018-11-20 10:49:39 +01:00
Mark Paluch
0220f69f3f DATAES-489 - After release cleanups. 2018-10-29 13:59:18 +01:00
Mark Paluch
c0dcda00e8 DATAES-489 - Prepare next development iteration. 2018-10-29 13:59:16 +01:00
Mark Paluch
cef1fc7d77 DATAES-489 - Release version 3.1.2 (Lovelace SR2). 2018-10-29 12:53:52 +01:00
Mark Paluch
9ddf4868ef DATAES-489 - Prepare 3.1.2 (Lovelace SR2). 2018-10-29 12:52:55 +01:00
Mark Paluch
dde561a805 DATAES-489 - Updated changelog. 2018-10-29 12:52:52 +01:00
Mark Paluch
950c48a069 DATAES-484 - Updated changelog. 2018-10-15 14:19:08 +02:00
Mark Paluch
df9954b3ef DATAES-485 - Updated changelog. 2018-10-15 12:46:30 +02:00
Mark Paluch
32d5f5dcb9 DATAES-486 - After release cleanups. 2018-10-15 11:12:14 +02:00
Mark Paluch
0191d69d94 DATAES-486 - Prepare next development iteration. 2018-10-15 11:12:13 +02:00
Mark Paluch
e7e0983ea5 DATAES-486 - Release version 3.1.1 (Lovelace SR1). 2018-10-15 10:42:05 +02:00
Mark Paluch
a299260a03 DATAES-486 - Prepare 3.1.1 (Lovelace SR1). 2018-10-15 10:40:57 +02:00
Mark Paluch
627d96cbfc DATAES-486 - Updated changelog. 2018-10-15 10:40:56 +02:00
Mark Paluch
efa3b4d17e DATAES-480 - After release cleanups. 2018-09-21 07:46:18 -04:00
Mark Paluch
f5d44ad755 DATAES-480 - Prepare next development iteration. 2018-09-21 07:46:17 -04:00
15 changed files with 346 additions and 75 deletions

View File

@ -4,12 +4,12 @@
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId> <artifactId>spring-data-elasticsearch</artifactId>
<version>3.1.0.RELEASE</version> <version>3.1.3.RELEASE</version>
<parent> <parent>
<groupId>org.springframework.data.build</groupId> <groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId> <artifactId>spring-data-parent</artifactId>
<version>2.1.0.RELEASE</version> <version>2.1.3.RELEASE</version>
</parent> </parent>
<name>Spring Data Elasticsearch</name> <name>Spring Data Elasticsearch</name>
@ -21,7 +21,7 @@
<commonslang>2.6</commonslang> <commonslang>2.6</commonslang>
<elasticsearch>6.2.2</elasticsearch> <elasticsearch>6.2.2</elasticsearch>
<log4j>2.9.1</log4j> <log4j>2.9.1</log4j>
<springdata.commons>2.1.0.RELEASE</springdata.commons> <springdata.commons>2.1.3.RELEASE</springdata.commons>
<java-module-name>spring.data.elasticsearch</java-module-name> <java-module-name>spring.data.elasticsearch</java-module-name>
</properties> </properties>

View File

@ -23,50 +23,55 @@ Page<SampleEntity> sampleEntities =
---- ----
==== ====
[[elasticsearch.scan.and.scroll]] [[elasticsearch.scroll]]
== Using Scan And Scroll For Big Result Set == Using Scroll For Big Result Set
Elasticsearch has scan and scroll feature for getting big result set in chunks. `ElasticsearchTemplate` has scan and scroll methods that can be used as below. Elasticsearch has a scroll API for getting big result set in chunks. `ElasticsearchTemplate` has startScroll and continueScroll methods that can be used as below.
.Using Scan and Scroll .Using startScroll and continueScroll
==== ====
[source,java] [source,java]
---- ----
SearchQuery searchQuery = new NativeSearchQueryBuilder() SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery()) .withQuery(matchAllQuery())
.withIndices("test-index") .withIndices(INDEX_NAME)
.withTypes("test-type") .withTypes(TYPE_NAME)
.withPageable(new PageRequest(0,1)) .withFields("message")
.withPageable(PageRequest.of(0, 10))
.build(); .build();
String scrollId = elasticsearchTemplate.scan(searchQuery,1000,false);
List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>(); Page<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class);
boolean hasRecords = true;
while (hasRecords){ String scrollId = ((ScrolledPage) scroll).getScrollId();
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L , new ResultsMapper<SampleEntity>() List<SampleEntity> sampleEntities = new ArrayList<>();
{ while (scroll.hasContent()) {
@Override sampleEntities.addAll(scroll.getContent());
public Page<SampleEntity> mapResults(SearchResponse response) { scrollId = ((ScrolledPage) scroll).getScrollId();
List<SampleEntity> chunk = new ArrayList<SampleEntity>(); scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class);
for(SearchHit searchHit : response.getHits()){ }
if(response.getHits().getHits().length <= 0) { elasticsearchTemplate.clearScroll(scrollId);
return null;
}
SampleEntity user = new SampleEntity();
user.setId(searchHit.getId());
user.setMessage((String)searchHit.getSource().get("message"));
chunk.add(user);
}
return new PageImpl<SampleEntity>(chunk);
}
});
if(page != null) {
sampleEntities.addAll(page.getContent());
hasRecords = page.hasNextPage();
}
else{
hasRecords = false;
}
}
}
---- ----
==== ====
`ElasticsearchTemplate` additionally has the stream method which wraps the scan and scroll operations into a CloseableIterator.
.Using stream
====
[source,java]
----
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices(INDEX_NAME)
.withTypes(TYPE_NAME)
.withFields("message")
.withPageable(PageRequest.of(0, 10))
.build();
CloseableIterator<SampleEntity> stream = elasticsearchTemplate.stream(searchQuery, SampleEntity.class);
List<SampleEntity> sampleEntities = new ArrayList<>();
while (stream.hasNext()) {
sampleEntities.add(stream.next());
}
----
====

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2013 the original author or authors. * Copyright 2013-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -52,7 +52,11 @@ public @interface Field {
String analyzer() default ""; String analyzer() default "";
String normalizer() default "";
String[] ignoreFields() default {}; String[] ignoreFields() default {};
boolean includeInParent() default false; boolean includeInParent() default false;
String[] copyTo() default {};
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2014 the original author or authors. * Copyright 2014-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,7 +21,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* * @author Artur Konczak
* @author Mohsin Husen
* @author Sascha Woo
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@ -44,4 +46,6 @@ public @interface InnerField {
String searchAnalyzer() default ""; String searchAnalyzer() default "";
String analyzer() default ""; String analyzer() default "";
String normalizer() default "";
} }

View File

@ -63,8 +63,10 @@ class MappingBuilder {
public static final String FIELD_FORMAT = "format"; public static final String FIELD_FORMAT = "format";
public static final String FIELD_SEARCH_ANALYZER = "search_analyzer"; public static final String FIELD_SEARCH_ANALYZER = "search_analyzer";
public static final String FIELD_INDEX_ANALYZER = "analyzer"; public static final String FIELD_INDEX_ANALYZER = "analyzer";
public static final String FIELD_NORMALIZER = "normalizer";
public static final String FIELD_PROPERTIES = "properties"; public static final String FIELD_PROPERTIES = "properties";
public static final String FIELD_PARENT = "_parent"; public static final String FIELD_PARENT = "_parent";
public static final String FIELD_COPY_TO = "copy_to";
public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators"; public static final String COMPLETION_PRESERVE_SEPARATORS = "preserve_separators";
public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments"; public static final String COMPLETION_PRESERVE_POSITION_INCREMENTS = "preserve_position_increments";
@ -269,6 +271,8 @@ class MappingBuilder {
String datePattern = null; String datePattern = null;
String analyzer = null; String analyzer = null;
String searchAnalyzer = null; String searchAnalyzer = null;
String normalizer = null;
String[] copyTo = null;
if (annotation instanceof Field) { if (annotation instanceof Field) {
// @Field // @Field
@ -281,6 +285,8 @@ class MappingBuilder {
datePattern = fieldAnnotation.pattern(); datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer(); analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer(); searchAnalyzer = fieldAnnotation.searchAnalyzer();
normalizer = fieldAnnotation.normalizer();
copyTo = fieldAnnotation.copyTo();
} else if (annotation instanceof InnerField) { } else if (annotation instanceof InnerField) {
// @InnerField // @InnerField
InnerField fieldAnnotation = (InnerField) annotation; InnerField fieldAnnotation = (InnerField) annotation;
@ -292,6 +298,7 @@ class MappingBuilder {
datePattern = fieldAnnotation.pattern(); datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer(); analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer(); searchAnalyzer = fieldAnnotation.searchAnalyzer();
normalizer = fieldAnnotation.normalizer();
} else { } else {
throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField"); throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField");
} }
@ -318,6 +325,12 @@ class MappingBuilder {
if (!StringUtils.isEmpty(searchAnalyzer)) { if (!StringUtils.isEmpty(searchAnalyzer)) {
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer); builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
} }
if (!StringUtils.isEmpty(normalizer)) {
builder.field(FIELD_NORMALIZER, normalizer);
}
if (copyTo != null && copyTo.length > 0) {
builder.field(FIELD_COPY_TO, copyTo);
}
} }
protected static boolean isEntity(java.lang.reflect.Field field) { protected static boolean isEntity(java.lang.reflect.Field field) {

View File

@ -35,13 +35,25 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
* {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity} * {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity}
* implementation to discover score property candidates on {@link ElasticsearchPersistentEntity} creation you should * implementation to discover score property candidates on {@link ElasticsearchPersistentEntity} creation you should
* rather call {@link ElasticsearchPersistentEntity#isScoreProperty(PersistentProperty)} to determine whether the * rather call {@link ElasticsearchPersistentEntity#isScoreProperty(PersistentProperty)} to determine whether the
* current property is the version property of that {@link ElasticsearchPersistentEntity} under consideration. * current property is the score property of that {@link ElasticsearchPersistentEntity} under consideration.
* *
* @return * @return
* @since 3.1 * @since 3.1
*/ */
boolean isScoreProperty(); boolean isScoreProperty();
/**
* Returns whether the current property is a <em>potential</em> parent property of the owning
* {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity}
* implementation to discover parent property candidates on {@link ElasticsearchPersistentEntity} creation you should
* rather call {@link ElasticsearchPersistentEntity#isParentProperty()} to determine whether the current property is
* the parent property of that {@link ElasticsearchPersistentEntity} under consideration.
*
* @return
* @since 3.1
*/
boolean isParentProperty();
public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> { public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> {
INSTANCE; INSTANCE;

View File

@ -170,18 +170,18 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
public void addPersistentProperty(ElasticsearchPersistentProperty property) { public void addPersistentProperty(ElasticsearchPersistentProperty property) {
super.addPersistentProperty(property); super.addPersistentProperty(property);
Parent annotation = property.findAnnotation(Parent.class); if (property.isParentProperty()) {
ElasticsearchPersistentProperty parentProperty = this.parentIdProperty;
if (annotation != null) { if (parentProperty != null) {
Assert.isNull(this.parentIdProperty, "Only one field can hold a @Parent annotation"); throw new MappingException(
Assert.isNull(this.parentType, "Only one field can hold a @Parent annotation"); String.format("Attempt to add parent property %s but already have property %s registered "
Assert.isTrue(property.getType() == String.class, "Parent ID property should be String"); + "as parent property. Check your mapping configuration!", property.getField(), parentProperty.getField()));
}
Parent parentAnnotation = property.findAnnotation(Parent.class);
this.parentIdProperty = property; this.parentIdProperty = property;
this.parentType = annotation.type(); this.parentType = parentAnnotation.type();
}
if (property.isVersionProperty()) {
Assert.isTrue(property.getType() == Long.class, "Version property must be of type Long!");
} }
if (property.isScoreProperty()) { if (property.isScoreProperty()) {
@ -191,7 +191,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
if (scoreProperty != null) { if (scoreProperty != null) {
throw new MappingException( throw new MappingException(
String.format("Attempt to add score property %s but already have property %s registered " String.format("Attempt to add score property %s but already have property %s registered "
+ "as version. Check your mapping configuration!", property.getField(), scoreProperty.getField())); + "as score property. Check your mapping configuration!", property.getField(), scoreProperty.getField()));
} }
this.scoreProperty = property; this.scoreProperty = property;

View File

@ -16,9 +16,9 @@
package org.springframework.data.elasticsearch.core.mapping; package org.springframework.data.elasticsearch.core.mapping;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.List;
import java.util.Set;
import org.springframework.data.elasticsearch.annotations.Parent;
import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.annotations.Score;
import org.springframework.data.mapping.Association; import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.MappingException; import org.springframework.data.mapping.MappingException;
@ -39,39 +39,57 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
public class SimpleElasticsearchPersistentProperty extends public class SimpleElasticsearchPersistentProperty extends
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty { AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>(); private static final List<String> SUPPORTED_ID_PROPERTY_NAMES = Arrays.asList("id", "document");
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>();
private final boolean isScore;
static { private final boolean isScore;
SUPPORTED_ID_TYPES.add(String.class); private final boolean isParent;
SUPPORTED_ID_PROPERTY_NAMES.add("id"); private final boolean isId;
SUPPORTED_ID_PROPERTY_NAMES.add("documentId");
}
public SimpleElasticsearchPersistentProperty(Property property, public SimpleElasticsearchPersistentProperty(Property property,
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) { PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder); super(property, owner, simpleTypeHolder);
this.isId = super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName());
this.isScore = isAnnotationPresent(Score.class); this.isScore = isAnnotationPresent(Score.class);
this.isParent = isAnnotationPresent(Parent.class);
if (isVersionProperty() && getType() != Long.class) {
throw new MappingException(String.format("Version property %s must be of type Long!", property.getName()));
}
if (isScore && !Arrays.asList(Float.TYPE, Float.class).contains(getType())) { if (isScore && !Arrays.asList(Float.TYPE, Float.class).contains(getType())) {
throw new MappingException(String.format("Score property %s must be either of type float or Float!", property.getName())); throw new MappingException(
String.format("Score property %s must be either of type float or Float!", property.getName()));
}
if (isParent && getType() != String.class) {
throw new MappingException(String.format("Parent property %s must be of type String!", property.getName()));
} }
} }
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#getFieldName()
*/
@Override @Override
public String getFieldName() { public String getFieldName() {
return getProperty().getName(); return getProperty().getName();
} }
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AnnotationBasedPersistentProperty#isIdProperty()
*/
@Override @Override
public boolean isIdProperty() { public boolean isIdProperty() {
return super.isIdProperty() || SUPPORTED_ID_PROPERTY_NAMES.contains(getFieldName()); return isId;
} }
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#createAssociation()
*/
@Override @Override
protected Association<ElasticsearchPersistentProperty> createAssociation() { protected Association<ElasticsearchPersistentProperty> createAssociation() {
return null; return null;
@ -85,7 +103,7 @@ public class SimpleElasticsearchPersistentProperty extends
public boolean isScoreProperty() { public boolean isScoreProperty() {
return isScore; return isScore;
} }
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#isImmutable() * @see org.springframework.data.mapping.model.AbstractPersistentProperty#isImmutable()
@ -94,4 +112,13 @@ public class SimpleElasticsearchPersistentProperty extends
public boolean isImmutable() { public boolean isImmutable() {
return false; return false;
} }
/*
* (non-Javadoc)
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#isParentProperty()
*/
@Override
public boolean isParentProperty() {
return isParent;
}
} }

View File

@ -1,6 +1,47 @@
Spring Data Elasticsearch Changelog Spring Data Elasticsearch Changelog
=================================== ===================================
Changes in version 3.1.3.RELEASE (2018-11-27)
---------------------------------------------
* DATAES-503 - Missing copy_to property in @Field Annotation.
* DATAES-496 - Release 3.1.3 (Lovelace SR3).
* DATAES-492 - Missing normalizer property in @Field and @InnerField Annotation.
* DATAES-445 - Usage example of scan and scroll is misleading.
Changes in version 3.0.12.RELEASE (2018-11-27)
----------------------------------------------
* DATAES-503 - Missing copy_to property in @Field Annotation.
* DATAES-492 - Missing normalizer property in @Field and @InnerField Annotation.
* DATAES-490 - Release 3.0.12 (Kay SR12).
* DATAES-445 - Usage example of scan and scroll is misleading.
Changes in version 2.1.17.RELEASE (2018-11-27)
----------------------------------------------
* DATAES-491 - Release 2.1.17 (Ingalls SR17).
Changes in version 3.1.2.RELEASE (2018-10-29)
---------------------------------------------
* DATAES-489 - Release 3.1.2 (Lovelace SR2).
Changes in version 2.1.16.RELEASE (2018-10-15)
----------------------------------------------
* DATAES-484 - Release 2.1.16 (Ingalls SR16).
Changes in version 3.0.11.RELEASE (2018-10-15)
----------------------------------------------
* DATAES-485 - Release 3.0.11 (Kay SR11).
Changes in version 3.1.1.RELEASE (2018-10-15)
---------------------------------------------
* DATAES-486 - Release 3.1.1 (Lovelace SR1).
Changes in version 3.1.0.RELEASE (2018-09-21) Changes in version 3.1.0.RELEASE (2018-09-21)
--------------------------------------------- ---------------------------------------------
* DATAES-480 - Release 3.1 GA (Lovelace). * DATAES-480 - Release 3.1 GA (Lovelace).

View File

@ -1,4 +1,4 @@
Spring Data Elasticsearch 3.1 GA Spring Data Elasticsearch 3.1.3
Copyright (c) [2013-2016] Pivotal Software, Inc. Copyright (c) [2013-2016] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License"). This product is licensed to you under the Apache License, Version 2.0 (the "License").

View File

@ -23,6 +23,7 @@ import static org.springframework.data.elasticsearch.utils.IndexBuilder.*;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -31,11 +32,21 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.builder.SampleInheritedEntityBuilder; import org.springframework.data.elasticsearch.builder.SampleInheritedEntityBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.entities.*; import org.springframework.data.elasticsearch.entities.Book;
import org.springframework.data.elasticsearch.entities.CopyToEntity;
import org.springframework.data.elasticsearch.entities.GeoEntity; import org.springframework.data.elasticsearch.entities.GeoEntity;
import org.springframework.data.elasticsearch.entities.Group;
import org.springframework.data.elasticsearch.entities.MinimalEntity;
import org.springframework.data.elasticsearch.entities.NormalizerEntity;
import org.springframework.data.elasticsearch.entities.SampleInheritedEntity;
import org.springframework.data.elasticsearch.entities.SampleTransientEntity;
import org.springframework.data.elasticsearch.entities.SimpleRecursiveEntity;
import org.springframework.data.elasticsearch.entities.StockPrice;
import org.springframework.data.elasticsearch.entities.User;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -45,6 +56,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Mohsin Husen * @author Mohsin Husen
* @author Keivn Leturc * @author Keivn Leturc
* @author Nordine Bittich * @author Nordine Bittich
* @author Sascha Woo
*/ */
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml") @ContextConfiguration("classpath:elasticsearch-template-test.xml")
@ -215,4 +227,45 @@ public class MappingBuilderTests {
assertThat(descriptionMapping.get("type"), equalTo("text")); assertThat(descriptionMapping.get("type"), equalTo("text"));
assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace")); assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace"));
} }
@Test // DATAES-492
public void shouldUseKeywordNormalizer() throws IOException {
// given
elasticsearchTemplate.deleteIndex(NormalizerEntity.class);
elasticsearchTemplate.createIndex(NormalizerEntity.class);
elasticsearchTemplate.putMapping(NormalizerEntity.class);
// when
Map mapping = elasticsearchTemplate.getMapping(NormalizerEntity.class);
Map properties = (Map) mapping.get("properties");
Map fieldName = (Map) properties.get("name");
Map fieldDescriptionLowerCase = (Map) ((Map) ((Map) properties.get("description")).get("fields")).get("lower_case");
// then
assertThat(fieldName.get("type"), equalTo("keyword"));
assertThat(fieldName.get("normalizer"), equalTo("lower_case_normalizer"));
assertThat(fieldDescriptionLowerCase.get("type"), equalTo("keyword"));
assertThat(fieldDescriptionLowerCase.get("normalizer"), equalTo("lower_case_normalizer"));
}
@Test // DATAES-503
public void shouldUseCopyTo() throws IOException {
// given
elasticsearchTemplate.deleteIndex(CopyToEntity.class);
elasticsearchTemplate.createIndex(CopyToEntity.class);
elasticsearchTemplate.putMapping(CopyToEntity.class);
// when
Map mapping = elasticsearchTemplate.getMapping(CopyToEntity.class);
Map properties = (Map) mapping.get("properties");
Map fieldFirstName = (Map) properties.get("firstName");
Map fieldLastName = (Map) properties.get("lastName");
// then
List<String> copyToValue = Arrays.asList("name");
assertThat(fieldFirstName.get("copy_to"), equalTo(copyToValue));
assertThat(fieldLastName.get("copy_to"), equalTo(copyToValue));
}
} }

View File

@ -37,7 +37,7 @@ import org.springframework.util.ReflectionUtils;
*/ */
public class SimpleElasticsearchPersistentEntityTests { public class SimpleElasticsearchPersistentEntityTests {
@Test(expected = IllegalArgumentException.class) @Test(expected = MappingException.class)
public void shouldThrowExceptionGivenVersionPropertyIsNotLong() throws NoSuchFieldException, IntrospectionException { public void shouldThrowExceptionGivenVersionPropertyIsNotLong() throws NoSuchFieldException, IntrospectionException {
// given // given
TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class); TypeInformation typeInformation = ClassTypeInformation.from(EntityWithWrongVersionType.class);

View File

@ -0,0 +1,47 @@
/*
* Copyright 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.entities;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* @author Sascha Woo
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(indexName = "test-copy-to", type = "test", shards = 1, replicas = 0, refreshInterval = "-1")
public class CopyToEntity {
@Id private String id;
@Field(type = FieldType.Keyword, copyTo = "name") private String firstName;
@Field(type = FieldType.Keyword, copyTo = "name") private String lastName;
@Field(type = FieldType.Keyword) private String name;
}

View File

@ -0,0 +1,52 @@
/*
* Copyright 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.elasticsearch.entities;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.InnerField;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.annotations.Setting;
/**
* @author Sascha Woo
*/
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Document(indexName = "test-index-normalizer", type = "test", shards = 1, replicas = 0, refreshInterval = "-1")
@Setting(settingPath = "/settings/test-normalizer.json")
public class NormalizerEntity {
@Id private String id;
@Field(type = FieldType.Keyword, normalizer = "lower_case_normalizer")
private String name;
@MultiField(mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "lower_case",
type = FieldType.Keyword, normalizer = "lower_case_normalizer") })
private String description;
}

View File

@ -0,0 +1,13 @@
{
"index": {
"analysis": {
"normalizer": {
"lower_case_normalizer": {
"type": "custom",
"char_filter": [],
"filter": [ "lowercase" ]
}
}
}
}
}