Skip to content

Commit 8862e01

Browse files
committed
added annotation for multfield
1 parent b2572d4 commit 8862e01

File tree

12 files changed

+168
-100
lines changed

12 files changed

+168
-100
lines changed

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,14 @@
2828
@Documented
2929
public @interface Field {
3030

31-
String type() default "";
31+
FieldType type() default FieldType.Auto;
3232

33-
String index() default "";
33+
FieldIndex index() default FieldIndex.analyzed;
3434

3535
boolean store() default false;
3636

3737
String searchAnalyzer() default "";
3838

3939
String indexAnalyzer() default "";
4040

41-
boolean facetable() default false;
42-
43-
boolean sortable() default false;
44-
4541
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.springframework.data.elasticsearch.annotations;
2+
3+
/**
4+
*/
5+
public enum FieldIndex {
6+
not_analyzed, analyzed
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.springframework.data.elasticsearch.annotations;
2+
3+
/**
4+
*/
5+
public enum FieldType {
6+
String, Integer, Long, Date, Object, Auto
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.springframework.data.elasticsearch.annotations;
2+
3+
import java.lang.annotation.*;
4+
5+
/**
6+
* @author Rizwan Idrees
7+
* @author Mohsin Husen
8+
* @author Artur Konczak
9+
* @author Jonathan Yan
10+
*/
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Target(ElementType.FIELD)
13+
@Documented
14+
public @interface MultiField {
15+
16+
public Field mainField();
17+
18+
public NestedField[] otherFields() default {};
19+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.springframework.data.elasticsearch.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
*
10+
*/
11+
@Retention(RetentionPolicy.RUNTIME)
12+
@Target(ElementType.FIELD)
13+
public @interface NestedField {
14+
15+
String dotSuffix();
16+
17+
FieldType type();
18+
19+
FieldIndex index() default FieldIndex.analyzed;
20+
21+
boolean store() default false;
22+
23+
String searchAnalyzer() default "";
24+
25+
String indexAnalyzer() default "";
26+
}

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

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
package org.springframework.data.elasticsearch.core;
1717

1818
import org.elasticsearch.common.xcontent.XContentBuilder;
19-
import org.springframework.data.elasticsearch.annotations.Field;
19+
import org.springframework.data.elasticsearch.annotations.*;
2020
import org.springframework.data.elasticsearch.core.query.FacetRequest;
2121
import org.springframework.data.mapping.model.SimpleTypeHolder;
2222
import org.springframework.data.util.ClassTypeInformation;
@@ -71,15 +71,14 @@ private static void mapEntity(XContentBuilder xContentBuilder, Class clazz, bool
7171
if (isEntity(field)) {
7272
mapEntity(xContentBuilder, field.getType(), false, EMPTY, field.getName());
7373
}
74-
Field fieldAnnotation = field.getAnnotation(Field.class);
75-
if (isRootObject && fieldAnnotation != null && isIdField(field, idFieldName)) {
74+
Field singleField = field.getAnnotation(Field.class);
75+
MultiField multiField = field.getAnnotation(MultiField.class);
76+
if (isRootObject && singleField != null && isIdField(field, idFieldName)) {
7677
applyDefaultIdFieldMapping(xContentBuilder, field);
77-
} else if (fieldAnnotation != null) {
78-
if ((fieldAnnotation.sortable() || fieldAnnotation.facetable()) && TYPE_VALUE_STRING.equals(fieldAnnotation.type())) {
79-
addMultiFieldMapping(xContentBuilder, field, fieldAnnotation);
80-
} else {
81-
addSimpleFieldMapping(xContentBuilder, field, fieldAnnotation);
82-
}
78+
} else if (multiField != null) {
79+
addMultiFieldMapping(xContentBuilder, field, multiField);
80+
} else if (singleField != null) {
81+
addSingleFieldMapping(xContentBuilder, field, singleField);
8382
}
8483
}
8584

@@ -105,15 +104,15 @@ private static void applyDefaultIdFieldMapping(XContentBuilder xContentBuilder,
105104
* @param fieldAnnotation
106105
* @throws IOException
107106
*/
108-
private static void addSimpleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
107+
private static void addSingleFieldMapping(XContentBuilder xContentBuilder, java.lang.reflect.Field field,
109108
Field fieldAnnotation) throws IOException {
110109
xContentBuilder.startObject(field.getName());
111110
xContentBuilder.field(FIELD_STORE, fieldAnnotation.store());
112-
if (isNotBlank(fieldAnnotation.type())) {
113-
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type());
111+
if (FieldType.Auto != fieldAnnotation.type()) {
112+
xContentBuilder.field(FIELD_TYPE, fieldAnnotation.type().name().toLowerCase());
114113
}
115-
if (isNotBlank(fieldAnnotation.index())) {
116-
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index());
114+
if (FieldIndex.not_analyzed == fieldAnnotation.index()) {
115+
xContentBuilder.field(FIELD_INDEX, fieldAnnotation.index().name().toLowerCase());
117116
}
118117
if (isNotBlank(fieldAnnotation.searchAnalyzer())) {
119118
xContentBuilder.field(FIELD_SEARCH_ANALYZER, fieldAnnotation.searchAnalyzer());
@@ -124,6 +123,33 @@ private static void addSimpleFieldMapping(XContentBuilder xContentBuilder, java.
124123
xContentBuilder.endObject();
125124
}
126125

126+
/**
127+
* Apply mapping for a single nested @Field annotation
128+
*
129+
* @param builder
130+
* @param field
131+
* @param annotation
132+
* @throws IOException
133+
*/
134+
private static void addNestedFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
135+
NestedField annotation) throws IOException {
136+
builder.startObject(field.getName() + "." + annotation.dotSuffix());
137+
builder.field(FIELD_STORE, annotation.store());
138+
if (FieldType.Auto != annotation.type()) {
139+
builder.field(FIELD_TYPE, annotation.type().name().toLowerCase());
140+
}
141+
if (FieldIndex.not_analyzed == annotation.index()) {
142+
builder.field(FIELD_INDEX, annotation.index().name().toLowerCase());
143+
}
144+
if (isNotBlank(annotation.searchAnalyzer())) {
145+
builder.field(FIELD_SEARCH_ANALYZER, annotation.searchAnalyzer());
146+
}
147+
if (isNotBlank(annotation.indexAnalyzer())) {
148+
builder.field(FIELD_INDEX_ANALYZER, annotation.indexAnalyzer());
149+
}
150+
builder.endObject();
151+
}
152+
127153
/**
128154
* Multi field mappings for string type fields, support for sorts and facets
129155
*
@@ -133,19 +159,14 @@ private static void addSimpleFieldMapping(XContentBuilder xContentBuilder, java.
133159
* @throws IOException
134160
*/
135161
private static void addMultiFieldMapping(XContentBuilder builder, java.lang.reflect.Field field,
136-
Field annotation) throws IOException {
162+
MultiField annotation) throws IOException {
137163
builder.startObject(field.getName());
138164
builder.field(FIELD_TYPE, "multi_field");
139165
builder.startObject("fields");
140166
//add standard field
141-
addSimpleFieldMapping(builder, field, annotation);
142-
//facet field - untouched, not analise, stored
143-
if (annotation.facetable()) {
144-
addFacetMapping(builder, field, annotation);
145-
}
146-
//sort field - lowercase, not analise, stored
147-
if (annotation.sortable()) {
148-
addSortMapping(builder, field, annotation);
167+
addSingleFieldMapping(builder, field, annotation.mainField());
168+
for (NestedField nestedField : annotation.otherFields()) {
169+
addNestedFieldMapping(builder, field, nestedField);
149170
}
150171
builder.endObject();
151172
builder.endObject();

src/main/java/org/springframework/data/elasticsearch/core/facet/FacetType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
public enum FacetType {
44

5-
term, renage, histogram
5+
term, range, histogram
66

77
}

src/main/java/org/springframework/data/elasticsearch/core/query/TermFacetRequest.java

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,16 @@
1919
*/
2020
public class TermFacetRequest extends AbstractFacetRequest {
2121

22-
private String[] stringFields;
23-
private String[] numberFields;
22+
private String[] fields;
2423
private int size = 10;
2524
private TermsFacet.ComparatorType order;
2625

2726
public TermFacetRequest(String name) {
2827
super(name);
2928
}
3029

31-
public void setStringFields(String... fields) {
32-
this.stringFields = fields;
33-
}
34-
35-
public void setNumberFields(String... fields) {
36-
this.numberFields = fields;
30+
public void setFields(String... fields) {
31+
this.fields = fields;
3732
}
3833

3934
public void setSize(int size) {
@@ -57,24 +52,10 @@ public void descCount() {
5752
order = TermsFacet.ComparatorType.COUNT;
5853
}
5954

60-
private List<String> convertStringFieldsToFullNames() {
61-
List<String> result = new ArrayList<String>();
62-
if (ArrayUtils.isNotEmpty(stringFields)) {
63-
for (String stringField : stringFields) {
64-
result.add(stringField + "." + FIELD_UNTOUCHED);
65-
}
66-
}
67-
if (ArrayUtils.isNotEmpty(numberFields)) {
68-
Collections.addAll(result, numberFields);
69-
}
70-
return result;
71-
}
72-
7355
@Override
7456
public FacetBuilder getFacet() {
75-
List<String> fields = convertStringFieldsToFullNames();
7657
Assert.notEmpty(fields, "Please select at last one field !!!");
77-
TermsFacetBuilder builder = FacetBuilders.termsFacet(getName()).fields(fields.toArray(new String[fields.size()])).size(size);
58+
TermsFacetBuilder builder = FacetBuilders.termsFacet(getName()).fields(fields).size(size);
7859
if (order != null) {
7960
builder.order(order);
8061
}

src/main/java/org/springframework/data/elasticsearch/core/query/TermFacetRequestBuilder.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,8 @@ public TermFacetRequestBuilder(String name) {
1313
result = new TermFacetRequest(name);
1414
}
1515

16-
public TermFacetRequestBuilder withStringFields(String... fields) {
17-
result.setStringFields(fields);
18-
return this;
19-
}
20-
21-
public TermFacetRequestBuilder withNumberFields(String... fields) {
22-
result.setNumberFields(fields);
16+
public TermFacetRequestBuilder withFields(String... fields) {
17+
result.setFields(fields);
2318
return this;
2419
}
2520

src/test/java/org/springframework/data/elasticsearch/Article.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package org.springframework.data.elasticsearch;
22

33
import org.springframework.data.annotation.Id;
4-
import org.springframework.data.elasticsearch.annotations.Document;
5-
import org.springframework.data.elasticsearch.annotations.Field;
4+
import org.springframework.data.elasticsearch.annotations.*;
65

76
import java.util.ArrayList;
87
import java.util.List;
98

9+
import static org.springframework.data.elasticsearch.annotations.FieldIndex.analyzed;
10+
import static org.springframework.data.elasticsearch.annotations.FieldIndex.not_analyzed;
11+
import static org.springframework.data.elasticsearch.annotations.FieldType.Integer;
12+
import static org.springframework.data.elasticsearch.annotations.FieldType.String;
13+
1014
/**
1115
* Simple type to test facets
1216
*/
@@ -18,10 +22,16 @@ public class Article {
1822

1923
private String title;
2024

21-
@Field(type = "string", facetable = true)
25+
@MultiField(
26+
mainField = @Field(type = String, index = analyzed),
27+
otherFields = {
28+
@NestedField(dotSuffix = "untouched", type = String, store = true, index = not_analyzed),
29+
@NestedField(dotSuffix = "sort", type = String, store = true, indexAnalyzer = "keyword")
30+
}
31+
)
2232
private List<String> authors = new ArrayList<String>();
2333

24-
@Field(type = "integer", facetable = true)
34+
@Field(type = Integer, store = true)
2535
private List<Integer> publishedYears = new ArrayList<Integer>();
2636

2737
public Article() {

src/test/java/org/springframework/data/elasticsearch/SampleMappingEntity.java

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
import org.springframework.data.annotation.Id;
1919
import org.springframework.data.elasticsearch.annotations.Document;
2020
import org.springframework.data.elasticsearch.annotations.Field;
21+
import org.springframework.data.elasticsearch.annotations.FieldIndex;
22+
import org.springframework.data.elasticsearch.annotations.FieldType;
23+
24+
import static org.springframework.data.elasticsearch.annotations.FieldIndex.*;
25+
import static org.springframework.data.elasticsearch.annotations.FieldType.*;
2126

2227
/**
2328
* @author Rizwan Idrees
@@ -26,40 +31,41 @@
2631
@Document(indexName = "test-mapping", type = "mapping", indexStoreType = "memory", shards = 1, replicas = 0, refreshInterval = "-1")
2732
public class SampleMappingEntity {
2833

29-
@Id
30-
private String id;
31-
@Field(type = "string", index = "not_analyzed", store = true, searchAnalyzer = "standard", indexAnalyzer = "standard")
32-
private String message;
34+
@Id
35+
private String id;
36+
37+
@Field(type = String, index = not_analyzed, store = true, searchAnalyzer = "standard", indexAnalyzer = "standard")
38+
private String message;
3339

34-
private NestedEntity nested;
40+
private NestedEntity nested;
3541

36-
public String getId() {
37-
return id;
38-
}
42+
public String getId() {
43+
return id;
44+
}
3945

40-
public void setId(String id) {
41-
this.id = id;
42-
}
46+
public void setId(String id) {
47+
this.id = id;
48+
}
4349

44-
public String getMessage() {
45-
return message;
46-
}
50+
public String getMessage() {
51+
return message;
52+
}
4753

48-
public void setMessage(String message) {
49-
this.message = message;
50-
}
54+
public void setMessage(String message) {
55+
this.message = message;
56+
}
5157

52-
static class NestedEntity {
53-
@Field(type = "string")
54-
private String someField;
58+
static class NestedEntity {
59+
@Field(type = String)
60+
private String someField;
5561

56-
public String getSomeField() {
57-
return someField;
58-
}
62+
public String getSomeField() {
63+
return someField;
64+
}
5965

60-
public void setSomeField(String someField) {
61-
this.someField = someField;
62-
}
63-
}
66+
public void setSomeField(String someField) {
67+
this.someField = someField;
68+
}
69+
}
6470

6571
}

0 commit comments

Comments
 (0)