mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-07-04 17:52:11 +00:00
DATAES-420 - Analyzer of main field ignored when using @MultiField annotation
This commit is contained in:
parent
36c52a5308
commit
1b0006f9f7
@ -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 "";
|
||||
}
|
||||
|
@ -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,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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user