1
0
mirror of synced 2026-05-31 16:43:22 +00:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Mark Paluch a1d508c656 DATAES-448 - Release version 3.0.8 (Kay SR8). 2018-06-13 15:13:01 +02:00
Mark Paluch 04308394dd DATAES-448 - Prepare 3.0.8 (Kay SR8). 2018-06-13 15:12:06 +02:00
Mark Paluch be80d7eae4 DATAES-448 - Updated changelog. 2018-06-13 15:12:04 +02:00
Mark Paluch de1c28979d DATAES-447 - Updated changelog. 2018-06-13 15:02:00 +02:00
Oliver Gierke bd668e6c2a DATAES-460 - Avoid Netty 3 dependency.
We now use a custom TransportClient implementation that reflectively pulls in the Netty transport client plugins. The previously used PreBuiltTransportClient expects both the Netty3 and the Netty 4 variant to be available at runtime. We now explicitly exclude Netty 3 so that Spring Data Elasticsearch projects run on Netty 4 by default.

Users required to stay on Netty 3 can explicitly declared the now excluded dependency.

Related tickets: https://github.com/elastic/elasticsearch/issues/31240
2018-06-11 14:11:25 +02:00
Christoph Strobl ba899a0017 DATAES-440 - Updated changelog. 2018-05-17 10:32:58 +02:00
Ted Liang 8181c713c7 DATAES-312 - Fix NullHandling.NULLS_LAST in query.sort
Original pull request: #163
2018-05-17 09:45:10 +02:00
Nordine Bittich c6419a1f05 DATAES-420 - Analyzer of main field ignored when using @MultiField annotation 2018-05-17 09:45:04 +02:00
Mark Paluch 09ee8f9026 DATAES-437 - After release cleanups. 2018-05-08 15:04:29 +02:00
Mark Paluch 13cfb039b5 DATAES-437 - Prepare next development iteration. 2018-05-08 15:04:27 +02:00
11 changed files with 389 additions and 86 deletions
+13 -11
View File
@@ -4,12 +4,12 @@
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>3.0.7.RELEASE</version>
<version>3.0.8.RELEASE</version>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.0.7.RELEASE</version>
<version>2.0.8.RELEASE</version>
</parent>
<name>Spring Data Elasticsearch</name>
@@ -21,7 +21,7 @@
<commonslang>2.6</commonslang>
<elasticsearch>5.5.0</elasticsearch>
<log4j>2.8.2</log4j>
<springdata.commons>2.0.7.RELEASE</springdata.commons>
<springdata.commons>2.0.8.RELEASE</springdata.commons>
<java-module-name>spring.data.elasticsearch</java-module-name>
</properties>
@@ -81,9 +81,19 @@
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty3-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
@@ -162,14 +172,6 @@
<scope>test</scope>
</dependency>
<dependency>
<!-- required by elasticsearch -->
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>transport-netty4-client</artifactId>
<version>${elasticsearch}</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -33,11 +33,15 @@ public @interface InnerField {
boolean index() default true;
DateFormat format() default DateFormat.none;
String pattern() default "";
boolean store() default false;
boolean fielddata() default false;
String searchAnalyzer() default "";
String indexAnalyzer() default "";
String analyzer() default "";
}
@@ -17,12 +17,29 @@ package org.springframework.data.elasticsearch.client;
import static org.apache.commons.lang.StringUtils.*;
import io.netty.util.ThreadDeathWatcher;
import io.netty.util.concurrent.GlobalEventExecutor;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.reindex.ReindexPlugin;
import org.elasticsearch.join.ParentJoinPlugin;
import org.elasticsearch.percolator.PercolatorPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,6 +47,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* TransportClientFactoryBean
@@ -88,7 +106,7 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
protected void buildClient() throws Exception {
client = new PreBuiltTransportClient(settings());
client = new SpringDataTransportClient(settings());
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");
for (String clusterNode : split(clusterNodes, COMMA)) {
String hostName = substringBeforeLast(clusterNode, COLON);
@@ -153,4 +171,97 @@ public class TransportClientFactoryBean implements FactoryBean<TransportClient>,
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* Pretty exact copy of {@link PreBuiltTransportClient} except that we're inspecting the classpath for Netty
* dependencies to only include the ones available. {@link PreBuiltTransportClient} expects both Netty 3 and Netty 4
* to be present.
*
* @author Oliver Gierke
* @see https://github.com/elastic/elasticsearch/issues/31240
*/
@SuppressWarnings("unchecked")
private static class SpringDataTransportClient extends TransportClient {
/**
* Netty wants to do some unwelcome things like use unsafe and replace a private field, or use a poorly considered
* buffer recycler. This method disables these things by default, but can be overridden by setting the corresponding
* system properties.
*/
private static void initializeNetty() {
/*
* We disable three pieces of Netty functionality here:
* - we disable Netty from being unsafe
* - we disable Netty from replacing the selector key set
* - we disable Netty from using the recycler
*
* While permissions are needed to read and set these, the permissions needed here are innocuous and thus should simply be granted
* rather than us handling a security exception here.
*/
setSystemPropertyIfUnset("io.netty.noUnsafe", Boolean.toString(true));
setSystemPropertyIfUnset("io.netty.noKeySetOptimization", Boolean.toString(true));
setSystemPropertyIfUnset("io.netty.recycler.maxCapacityPerThread", Integer.toString(0));
}
@SuppressForbidden(reason = "set system properties to configure Netty")
private static void setSystemPropertyIfUnset(final String key, final String value) {
final String currentValue = System.getProperty(key);
if (currentValue == null) {
System.setProperty(key, value);
}
}
private static final List<String> OPTIONAL_DEPENDENCIES = Arrays.asList( //
"org.elasticsearch.transport.Netty3Plugin", //
"org.elasticsearch.transport.Netty4Plugin");
private static final Collection<Class<? extends Plugin>> PRE_INSTALLED_PLUGINS;
static {
initializeNetty();
List<Class<? extends Plugin>> plugins = new ArrayList<>();
boolean found = false;
for (String dependency : OPTIONAL_DEPENDENCIES) {
try {
plugins.add((Class<? extends Plugin>) ClassUtils.forName(dependency,
SpringDataTransportClient.class.getClassLoader()));
found = true;
} catch (ClassNotFoundException | LinkageError e) {}
}
Assert.state(found, "Neither Netty 3 or Netty 4 plugin found on the classpath. One of them is required to run the transport client!");
plugins.add(ReindexPlugin.class);
plugins.add(PercolatorPlugin.class);
plugins.add(MustachePlugin.class);
plugins.add(ParentJoinPlugin.class);
PRE_INSTALLED_PLUGINS = Collections.unmodifiableList(plugins);
}
public SpringDataTransportClient(Settings settings) {
super(settings, PRE_INSTALLED_PLUGINS);
}
@Override
public void close() {
super.close();
if (NetworkModule.TRANSPORT_TYPE_SETTING.exists(settings) == false
|| NetworkModule.TRANSPORT_TYPE_SETTING.get(settings).equals(Netty4Plugin.NETTY_TRANSPORT_NAME)) {
try {
GlobalEventExecutor.INSTANCE.awaitInactivity(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
try {
ThreadDeathWatcher.awaitInactivity(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
@@ -59,7 +59,9 @@ import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.slf4j.Logger;
@@ -108,6 +110,7 @@ import static org.springframework.util.CollectionUtils.isEmpty;
* @author Chris White
* @author Mark Paluch
* @author Sascha Woo
* @author Ted Liang
*/
public class ElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
@@ -1003,8 +1006,15 @@ public class ElasticsearchTemplate implements ElasticsearchOperations, Applicati
if (query.getSort() != null) {
for (Sort.Order order : query.getSort()) {
searchRequestBuilder.addSort(order.getProperty(),
order.getDirection() == Sort.Direction.DESC ? SortOrder.DESC : SortOrder.ASC);
FieldSortBuilder sort = SortBuilders.fieldSort(order.getProperty())
.order(order.getDirection().isDescending() ? SortOrder.DESC : SortOrder.ASC);
if (order.getNullHandling() == Sort.NullHandling.NULLS_FIRST) {
sort.missing("_first");
}
else if (order.getNullHandling() == Sort.NullHandling.NULLS_LAST) {
sort.missing("_last");
}
searchRequestBuilder.addSort(sort);
}
}
@@ -51,6 +51,7 @@ import static org.springframework.util.StringUtils.*;
* @author Pavel Luhin
* @author Mark Paluch
* @author Sascha Woo
* @author Nordine Bittich
*/
class MappingBuilder {
@@ -221,83 +222,101 @@ class MappingBuilder {
}
/**
* Apply mapping for a single @Field annotation
* Add mapping for @Field annotation
*
* @throws IOException
*/
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
xContentBuilder.startObject(field.getName());
if(!nestedOrObjectField) {
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
private static void addSingleFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation, boolean nestedOrObjectField) throws IOException {
builder.startObject(field.getName());
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
builder.endObject();
}
/**
* Add mapping for @MultiField annotation
*
* @throws IOException
*/
private static void addMultiFieldMapping(
XContentBuilder builder,
java.lang.reflect.Field field,
MultiField annotation,
boolean nestedOrObjectField) throws IOException {
// main field
builder.startObject(field.getName());
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
// inner fields
builder.startObject("fields");
for (InnerField innerField : annotation.otherFields()) {
builder.startObject(innerField.suffix());
addFieldMappingParameters(builder, innerField, false);
builder.endObject();
}
if(fieldAnnotation.fielddata()) {
xContentBuilder.field(FIELD_DATA, fieldAnnotation.fielddata());
builder.endObject();
builder.endObject();
}
private static void addFieldMappingParameters(XContentBuilder builder, Object annotation, boolean nestedOrObjectField) throws IOException {
boolean index = true;
boolean store = false;
boolean fielddata = false;
FieldType type = null;
DateFormat dateFormat = null;
String datePattern = null;
String analyzer = null;
String searchAnalyzer = null;
if (annotation instanceof Field) {
// @Field
Field fieldAnnotation = (Field) annotation;
index = fieldAnnotation.index();
store = fieldAnnotation.store();
fielddata = fieldAnnotation.fielddata();
type = fieldAnnotation.type();
dateFormat = fieldAnnotation.format();
datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer();
} else if (annotation instanceof InnerField) {
// @InnerField
InnerField fieldAnnotation = (InnerField) annotation;
index = fieldAnnotation.index();
store = fieldAnnotation.store();
fielddata = fieldAnnotation.fielddata();
type = fieldAnnotation.type();
dateFormat = fieldAnnotation.format();
datePattern = fieldAnnotation.pattern();
analyzer = fieldAnnotation.analyzer();
searchAnalyzer = fieldAnnotation.searchAnalyzer();
} else {
throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField");
}
if (FieldType.Auto != fieldAnnotation.type()) {
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format()
? fieldAnnotation.pattern() : fieldAnnotation.format());
if (!nestedOrObjectField) {
builder.field(FIELD_STORE, store);
}
if (fielddata) {
builder.field(FIELD_DATA, fielddata);
}
if (type != FieldType.Auto) {
builder.field(FIELD_TYPE, type.name().toLowerCase());
if (type == FieldType.Date && dateFormat != DateFormat.none) {
builder.field(FIELD_FORMAT, dateFormat == DateFormat.custom ? datePattern : dateFormat.toString());
}
}
if(!fieldAnnotation.index()) {
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
if (!index) {
builder.field(FIELD_INDEX, index);
}
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
if (isNotBlank(analyzer)) {
builder.field(FIELD_INDEX_ANALYZER, analyzer);
}
if (isNotBlank(fieldAnnotation.analyzer())) {
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
if (isNotBlank(searchAnalyzer)) {
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
}
xContentBuilder.endObject();
}
/**
* Apply mapping for a single nested @Field annotation
*
* @throws IOException
*/
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
InnerField annotation) throws IOException {
builder.startObject(annotation.suffix());
//builder.field(FIELD_STORE, annotation.store());
if (FieldType.Auto != annotation.type()) {
builder.field(FIELD_TYPE, annotation.type().name().toLowerCase());
}
if(!annotation.index()) {
builder.field(FIELD_INDEX, annotation.index());
}
if (isNotBlank(annotation.searchAnalyzer())) {
builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
}
if (isNotBlank(annotation.indexAnalyzer())) {
builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
}
if (annotation.fielddata()) {
builder.field(FIELD_DATA, annotation.fielddata());
}
builder.endObject();
}
/**
* Multi field mappings for string type fields, support for sorts and facets
*
* @throws IOException
*/
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
MultiField annotation, boolean nestedOrObjectField) throws IOException {
builder.startObject(field.getName());
builder.field(FIELD_TYPE, annotation.mainField().type().name().toLowerCase());
builder.startObject("fields");
//add standard field
//addSingleFieldMapping(builder, field, annotation.mainField(), nestedOrObjectField);
for (InnerField innerField : annotation.otherFields()) {
addNestedFieldMapping(builder, field, innerField);
}
builder.endObject();
builder.endObject();
}
protected static boolean isEntity(java.lang.reflect.Field field) {
+25
View File
@@ -1,6 +1,31 @@
Spring Data Elasticsearch Changelog
===================================
Changes in version 3.0.8.RELEASE (2018-06-13)
---------------------------------------------
* DATAES-460 - Avoid pulling in Netty 3 as dependency.
* DATAES-448 - Release 3.0.8 (Kay SR8).
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
Changes in version 2.1.13.RELEASE (2018-06-13)
----------------------------------------------
* DATAES-447 - Release 2.1.13 (Ingalls SR13).
Changes in version 3.1.0.M3 (2018-05-17)
----------------------------------------
* DATAES-451 - Adapt to SpEL extension API changes in Spring Data Commons.
* DATAES-440 - Release 3.1 M3 (Lovelace).
* DATAES-422 - Add support for IndicesOptions in search queries.
* DATAES-420 - Analyzer of main field ignored when using @MultiField annotation.
* DATAES-412 - Highlighted fields is not getting passed to the elastic search query.
* DATAES-363 - AbstractElasticsearchRepository.existsById(..) always returns true.
* DATAES-312 - NullHandling.NULLS_LAST not working in query.sort.
* DATAES-198 - @Version has no effect, so therefore is not useful with spring data elasticsearch.
Changes in version 3.0.7.RELEASE (2018-05-08)
---------------------------------------------
* DATAES-438 - Expected a boolean [true/false] for property [index] but got [not_analyzed].
+1 -1
View File
@@ -1,4 +1,4 @@
Spring Data Elasticsearch 3.0.7
Spring Data Elasticsearch 3.0.8
Copyright (c) [2013-2016] Pivotal Software, Inc.
This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -464,6 +464,106 @@ public class ElasticsearchTemplateTests {
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
}
@Test // DATAES-312
public void shouldSortResultsGivenNullFirstSortCriteria() {
// given
List<IndexQuery> indexQueries;
// first document
String documentId = randomNumeric(5);
SampleEntity sampleEntity1 = SampleEntity.builder()
.id(documentId)
.message("abc")
.rate(15)
.version(System.currentTimeMillis())
.build();
// second document
String documentId2 = randomNumeric(5);
SampleEntity sampleEntity2 = SampleEntity.builder()
.id(documentId2)
.message("xyz")
.rate(5)
.version(System.currentTimeMillis())
.build();
// third document
String documentId3 = randomNumeric(5);
SampleEntity sampleEntity3 = SampleEntity.builder()
.id(documentId3)
.rate(10)
.version(System.currentTimeMillis())
.build();
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsFirst())))
.build();
// when
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
// then
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity3.getRate()));
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity1.getMessage()));
}
@Test // DATAES-312
public void shouldSortResultsGivenNullLastSortCriteria() {
// given
List<IndexQuery> indexQueries;
// first document
String documentId = randomNumeric(5);
SampleEntity sampleEntity1 = SampleEntity.builder()
.id(documentId)
.message("abc")
.rate(15)
.version(System.currentTimeMillis())
.build();
// second document
String documentId2 = randomNumeric(5);
SampleEntity sampleEntity2 = SampleEntity.builder()
.id(documentId2)
.message("xyz")
.rate(5)
.version(System.currentTimeMillis())
.build();
// third document
String documentId3 = randomNumeric(5);
SampleEntity sampleEntity3 = SampleEntity.builder()
.id(documentId3)
.rate(10)
.version(System.currentTimeMillis())
.build();
indexQueries = getIndexQueries(Arrays.asList(sampleEntity1, sampleEntity2, sampleEntity3));
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(SampleEntity.class);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withPageable(PageRequest.of(0, 10, Sort.by(Sort.Order.asc("message").nullsLast())))
.build();
// when
Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class);
// then
assertThat(sampleEntities.getTotalElements(), equalTo(3L));
assertThat(sampleEntities.getContent().get(0).getRate(), is(sampleEntity1.getRate()));
assertThat(sampleEntities.getContent().get(1).getMessage(), is(sampleEntity2.getMessage()));
}
@Test
public void shouldExecuteStringQuery() {
// given
@@ -2070,4 +2170,4 @@ public class ElasticsearchTemplateTests {
this.lastName = lastName;
}
}
}
}
@@ -25,6 +25,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.junit.Test;
@@ -43,6 +44,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @author Jakub Vavrik
* @author Mohsin Husen
* @author Keivn Leturc
* @author Nordine Bittich
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
@@ -189,8 +191,28 @@ public class MappingBuilderTests {
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
//when
//then
}
@Test // DATAES-420
public void shouldUseBothAnalyzer() {
//given
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
//when
Map mapping = elasticsearchTemplate.getMapping(Book.class);
Map descriptionMapping = (Map) ((Map) mapping.get("properties")).get("description");
Map prefixDescription = (Map) ((Map) descriptionMapping.get("fields")).get("prefix");
//then
assertThat(prefixDescription.size(), is(3));
assertThat(prefixDescription.get("type"), equalTo("text"));
assertThat(prefixDescription.get("analyzer"), equalTo("stop"));
assertThat(prefixDescription.get("search_analyzer"), equalTo("standard"));
assertThat(descriptionMapping.get("type"), equalTo("text"));
assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace"));
}
}
@@ -42,8 +42,8 @@ public class ArticleEntity {
@MultiField(
mainField = @Field(type = Text),
otherFields = {
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, indexAnalyzer = "keyword"),
@InnerField(suffix = "sort", type = Text, store = true, indexAnalyzer = "keyword")
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, analyzer = "keyword"),
@InnerField(suffix = "sort", type = Text, store = true, analyzer = "keyword")
}
)
private List<String> authors = new ArrayList<>();
@@ -29,10 +29,13 @@ 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;
/**
* @author Rizwan Idrees
* @author Mohsin Husen
* @author Nordine Bittich
*/
@Setter
@Getter
@@ -49,4 +52,11 @@ public class Book {
private Author author;
@Field(type = FieldType.Nested)
private Map<Integer, Collection<String>> buckets = new HashMap<>();
@MultiField(
mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
otherFields = {
@InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard")
}
)
private String description;
}