Skip to content

Commit 1b0006f

Browse files
Nordine Bittichxhaggi
authored andcommitted
DATAES-420 - Analyzer of main field ignored when using @MultiField annotation
1 parent 36c52a5 commit 1b0006f

File tree

5 files changed

+120
-65
lines changed

5 files changed

+120
-65
lines changed

src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@
3333

3434
boolean index() default true;
3535

36+
DateFormat format() default DateFormat.none;
37+
38+
String pattern() default "";
39+
3640
boolean store() default false;
3741

3842
boolean fielddata() default false;
3943

4044
String searchAnalyzer() default "";
4145

42-
String indexAnalyzer() default "";
46+
String analyzer() default "";
4347
}

src/main/java/org/springframework/data/elasticsearch/core/MappingBuilder.java

Lines changed: 80 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* @author Pavel Luhin
5252
* @author Mark Paluch
5353
* @author Sascha Woo
54+
* @author Nordine Bittich
5455
*/
5556
class MappingBuilder {
5657

@@ -221,85 +222,103 @@ private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder,
221222
}
222223

223224
/**
224-
* Apply mapping for a single @Field annotation
225+
* Add mapping for @Field annotation
225226
*
226227
* @throws IOException
227228
*/
228-
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
229-
Field fieldAnnotation, boolean nestedOrObjectField) throws IOException {
230-
xContentBuilder.startObject(field.getName());
231-
if(!nestedOrObjectField) {
232-
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
233-
}
234-
if(fieldAnnotation.fielddata()) {
235-
xContentBuilder.field(FIELD_DATA, fieldAnnotation.fielddata());
236-
}
237-
238-
if (FieldType.Auto != fieldAnnotation.type()) {
239-
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
240-
if (FieldType.Date == fieldAnnotation.type() && DateFormat.none != fieldAnnotation.format()) {
241-
xContentBuilder.field(FIELD_FORMAT, DateFormat.custom == fieldAnnotation.format()
242-
? fieldAnnotation.pattern() : fieldAnnotation.format());
243-
}
244-
}
245-
if(!fieldAnnotation.index()) {
246-
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
247-
}
248-
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
249-
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
250-
}
251-
if (isNotBlank(fieldAnnotation.analyzer())) {
252-
xContentBuilder.field(FIELD_INDEX_ANALYZER, fieldAnnotation.analyzer());
253-
}
254-
xContentBuilder.endObject();
255-
}
256-
257-
/**
258-
* Apply mapping for a single nested @Field annotation
259-
*
260-
* @throws IOException
261-
*/
262-
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
263-
InnerField annotation) throws IOException {
264-
builder.startObject(annotation.suffix());
265-
//builder.field(FIELD_STORE, annotation.store());
266-
if (FieldType.Auto != annotation.type()) {
267-
builder.field(FIELD_TYPE, annotation.type().name().toLowerCase());
268-
}
269-
if(!annotation.index()) {
270-
builder.field(FIELD_INDEX, annotation.index());
271-
}
272-
if (isNotBlank(annotation.searchAnalyzer())) {
273-
builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
274-
}
275-
if (isNotBlank(annotation.indexAnalyzer())) {
276-
builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
277-
}
278-
if (annotation.fielddata()) {
279-
builder.field(FIELD_DATA, annotation.fielddata());
280-
}
229+
private static void addSingleFieldMapping(XContentBuilder builder, java.lang.reflect.Field field, Field annotation, boolean nestedOrObjectField) throws IOException {
230+
builder.startObject(field.getName());
231+
addFieldMappingParameters(builder, annotation, nestedOrObjectField);
281232
builder.endObject();
282233
}
283234

284235
/**
285-
* Multi field mappings for string type fields, support for sorts and facets
236+
* Add mapping for @MultiField annotation
286237
*
287238
* @throws IOException
288239
*/
289-
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
290-
MultiField annotation, boolean nestedOrObjectField) throws IOException {
240+
private static void addMultiFieldMapping(
241+
XContentBuilder builder,
242+
java.lang.reflect.Field field,
243+
MultiField annotation,
244+
boolean nestedOrObjectField) throws IOException {
245+
246+
// main field
291247
builder.startObject(field.getName());
292-
builder.field(FIELD_TYPE, annotation.mainField().type().name().toLowerCase());
248+
addFieldMappingParameters(builder, annotation.mainField(), nestedOrObjectField);
249+
250+
// inner fields
293251
builder.startObject("fields");
294-
//add standard field
295-
//addSingleFieldMapping(builder, field, annotation.mainField(), nestedOrObjectField);
296252
for (InnerField innerField : annotation.otherFields()) {
297-
addNestedFieldMapping(builder, field, innerField);
253+
builder.startObject(innerField.suffix());
254+
addFieldMappingParameters(builder, innerField, false);
255+
builder.endObject();
298256
}
299257
builder.endObject();
258+
300259
builder.endObject();
301260
}
302261

262+
private static void addFieldMappingParameters(XContentBuilder builder, Object annotation, boolean nestedOrObjectField) throws IOException {
263+
boolean index = true;
264+
boolean store = false;
265+
boolean fielddata = false;
266+
FieldType type = null;
267+
DateFormat dateFormat = null;
268+
String datePattern = null;
269+
String analyzer = null;
270+
String searchAnalyzer = null;
271+
272+
if (annotation instanceof Field) {
273+
// @Field
274+
Field fieldAnnotation = (Field) annotation;
275+
index = fieldAnnotation.index();
276+
store = fieldAnnotation.store();
277+
fielddata = fieldAnnotation.fielddata();
278+
type = fieldAnnotation.type();
279+
dateFormat = fieldAnnotation.format();
280+
datePattern = fieldAnnotation.pattern();
281+
analyzer = fieldAnnotation.analyzer();
282+
searchAnalyzer = fieldAnnotation.searchAnalyzer();
283+
} else if (annotation instanceof InnerField) {
284+
// @InnerField
285+
InnerField fieldAnnotation = (InnerField) annotation;
286+
index = fieldAnnotation.index();
287+
store = fieldAnnotation.store();
288+
fielddata = fieldAnnotation.fielddata();
289+
type = fieldAnnotation.type();
290+
dateFormat = fieldAnnotation.format();
291+
datePattern = fieldAnnotation.pattern();
292+
analyzer = fieldAnnotation.analyzer();
293+
searchAnalyzer = fieldAnnotation.searchAnalyzer();
294+
} else {
295+
throw new IllegalArgumentException("annotation must be an instance of @Field or @InnerField");
296+
}
297+
298+
if (!nestedOrObjectField) {
299+
builder.field(FIELD_STORE, store);
300+
}
301+
if (fielddata) {
302+
builder.field(FIELD_DATA, fielddata);
303+
}
304+
if (type != FieldType.Auto) {
305+
builder.field(FIELD_TYPE, type.name().toLowerCase());
306+
307+
if (type == FieldType.Date && dateFormat != DateFormat.none) {
308+
builder.field(FIELD_FORMAT, dateFormat == DateFormat.custom ? datePattern : dateFormat.toString());
309+
}
310+
}
311+
if (!index) {
312+
builder.field(FIELD_INDEX, index);
313+
}
314+
if (isNotBlank(analyzer)) {
315+
builder.field(FIELD_INDEX_ANALYZER, analyzer);
316+
}
317+
if (isNotBlank(searchAnalyzer)) {
318+
builder.field(FIELD_SEARCH_ANALYZER, searchAnalyzer);
319+
}
320+
}
321+
303322
protected static boolean isEntity(java.lang.reflect.Field field) {
304323
TypeInformation typeInformation = ClassTypeInformation.from(field.getType());
305324
Class<?> clazz = getFieldType(field);

src/test/java/org/springframework/data/elasticsearch/core/MappingBuilderTests.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.math.BigDecimal;
2626
import java.util.Date;
2727
import java.util.List;
28+
import java.util.Map;
2829

2930
import org.elasticsearch.common.xcontent.XContentBuilder;
3031
import org.junit.Test;
@@ -43,6 +44,7 @@
4344
* @author Jakub Vavrik
4445
* @author Mohsin Husen
4546
* @author Keivn Leturc
47+
* @author Nordine Bittich
4648
*/
4749
@RunWith(SpringJUnit4ClassRunner.class)
4850
@ContextConfiguration("classpath:elasticsearch-template-test.xml")
@@ -189,8 +191,28 @@ public void shouldMapBooks() {
189191
elasticsearchTemplate.createIndex(Book.class);
190192
elasticsearchTemplate.putMapping(Book.class);
191193
//when
192-
193194
//then
194195

195196
}
197+
198+
@Test // DATAES-420
199+
public void shouldUseBothAnalyzer() {
200+
//given
201+
elasticsearchTemplate.deleteIndex(Book.class);
202+
elasticsearchTemplate.createIndex(Book.class);
203+
elasticsearchTemplate.putMapping(Book.class);
204+
205+
//when
206+
Map mapping = elasticsearchTemplate.getMapping(Book.class);
207+
Map descriptionMapping = (Map) ((Map) mapping.get("properties")).get("description");
208+
Map prefixDescription = (Map) ((Map) descriptionMapping.get("fields")).get("prefix");
209+
210+
//then
211+
assertThat(prefixDescription.size(), is(3));
212+
assertThat(prefixDescription.get("type"), equalTo("text"));
213+
assertThat(prefixDescription.get("analyzer"), equalTo("stop"));
214+
assertThat(prefixDescription.get("search_analyzer"), equalTo("standard"));
215+
assertThat(descriptionMapping.get("type"), equalTo("text"));
216+
assertThat(descriptionMapping.get("analyzer"), equalTo("whitespace"));
217+
}
196218
}

src/test/java/org/springframework/data/elasticsearch/core/facet/ArticleEntity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public class ArticleEntity {
4242
@MultiField(
4343
mainField = @Field(type = Text),
4444
otherFields = {
45-
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, indexAnalyzer = "keyword"),
46-
@InnerField(suffix = "sort", type = Text, store = true, indexAnalyzer = "keyword")
45+
@InnerField(suffix = "untouched", type = Text, store = true, fielddata = true, analyzer = "keyword"),
46+
@InnerField(suffix = "sort", type = Text, store = true, analyzer = "keyword")
4747
}
4848
)
4949
private List<String> authors = new ArrayList<>();

src/test/java/org/springframework/data/elasticsearch/entities/Book.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@
2929
import org.springframework.data.elasticsearch.annotations.Document;
3030
import org.springframework.data.elasticsearch.annotations.Field;
3131
import org.springframework.data.elasticsearch.annotations.FieldType;
32+
import org.springframework.data.elasticsearch.annotations.InnerField;
33+
import org.springframework.data.elasticsearch.annotations.MultiField;
3234

3335
/**
3436
* @author Rizwan Idrees
3537
* @author Mohsin Husen
38+
* @author Nordine Bittich
3639
*/
3740
@Setter
3841
@Getter
@@ -49,4 +52,11 @@ public class Book {
4952
private Author author;
5053
@Field(type = FieldType.Nested)
5154
private Map<Integer, Collection<String>> buckets = new HashMap<>();
55+
@MultiField(
56+
mainField = @Field(type = FieldType.Text, analyzer = "whitespace"),
57+
otherFields = {
58+
@InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard")
59+
}
60+
)
61+
private String description;
5262
}

0 commit comments

Comments
 (0)