Skip to content

Commit fd23c10

Browse files
authored
DATAES-896 - Use mainField property of @MultiField annotation.
Original PR: spring-projects#500
1 parent fd77f62 commit fd23c10

File tree

6 files changed

+71
-21
lines changed

6 files changed

+71
-21
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* @author Aleksei Arsenev
3030
*/
3131
@Retention(RetentionPolicy.RUNTIME)
32-
@Target(ElementType.FIELD)
32+
@Target(ElementType.ANNOTATION_TYPE)
3333
public @interface InnerField {
3434

3535
String suffix();

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ public String buildPropertyMapping(Class<?> clazz) throws ElasticsearchException
133133
}
134134
}
135135

136-
private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject,
137-
String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType,
136+
private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity<?> entity,
137+
boolean isRootObject, String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType,
138138
@Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping) throws IOException {
139139

140140
boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField);
@@ -146,7 +146,7 @@ private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersisten
146146

147147
if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null
148148
&& parentFieldAnnotation.includeInParent()) {
149-
builder.field("include_in_parent", parentFieldAnnotation.includeInParent());
149+
builder.field("include_in_parent", true);
150150
}
151151
}
152152

@@ -396,7 +396,7 @@ private void addFieldMappingParameters(XContentBuilder builder, Annotation annot
396396
MappingParameters mappingParameters = MappingParameters.from(annotation);
397397

398398
if (!nestedOrObjectField && mappingParameters.isStore()) {
399-
builder.field(FIELD_PARAM_STORE, mappingParameters.isStore());
399+
builder.field(FIELD_PARAM_STORE, true);
400400
}
401401
mappingParameters.writeTypeAndParametersTo(builder);
402402
}

src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.data.elasticsearch.annotations.DateFormat;
2727
import org.springframework.data.elasticsearch.annotations.Field;
2828
import org.springframework.data.elasticsearch.annotations.FieldType;
29+
import org.springframework.data.elasticsearch.annotations.MultiField;
2930
import org.springframework.data.elasticsearch.annotations.Parent;
3031
import org.springframework.data.elasticsearch.annotations.Score;
3132
import org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter;
@@ -97,6 +98,10 @@ public SimpleElasticsearchPersistentProperty(Property property,
9798
throw new MappingException(String.format("Parent property %s must be of type String!", property.getName()));
9899
}
99100

101+
if (isAnnotationPresent(Field.class) && isAnnotationPresent(MultiField.class)) {
102+
throw new MappingException("@Field annotation must not be used on a @MultiField property.");
103+
}
104+
100105
initDateConverter();
101106
}
102107

@@ -182,13 +187,15 @@ public Object read(String s) {
182187
@Nullable
183188
private String getAnnotatedFieldName() {
184189

185-
if (isAnnotationPresent(Field.class)) {
190+
String name = null;
186191

187-
String name = findAnnotation(Field.class).name();
188-
return StringUtils.hasText(name) ? name : null;
192+
if (isAnnotationPresent(Field.class)) {
193+
name = findAnnotation(Field.class).name();
194+
} else if (isAnnotationPresent(MultiField.class)) {
195+
name = findAnnotation(MultiField.class).mainField().name();
189196
}
190197

191-
return null;
198+
return StringUtils.hasText(name) ? name : null;
192199
}
193200

194201
/*

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

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.HashSet;
4343
import java.util.List;
4444
import java.util.Map;
45+
import java.util.Objects;
4546
import java.util.Set;
4647

4748
import org.assertj.core.data.Percentage;
@@ -255,6 +256,7 @@ public void shouldMapBooks() {
255256
}
256257

257258
@Test // DATAES-420
259+
@SuppressWarnings({ "rawtypes", "unchecked" })
258260
public void shouldUseBothAnalyzer() {
259261

260262
// given
@@ -277,6 +279,7 @@ public void shouldUseBothAnalyzer() {
277279
}
278280

279281
@Test // DATAES-492
282+
@SuppressWarnings("rawtypes")
280283
public void shouldUseKeywordNormalizer() {
281284

282285
// given
@@ -297,6 +300,7 @@ public void shouldUseKeywordNormalizer() {
297300
}
298301

299302
@Test // DATAES-503
303+
@SuppressWarnings("rawtypes")
300304
public void shouldUseCopyTo() {
301305

302306
// given
@@ -400,12 +404,29 @@ public void shouldUseFieldNameOnCompletion() throws JSONException {
400404
assertEquals(expected, mapping, false);
401405
}
402406

403-
@Test // DATAES-568
407+
@Test // DATAES-568, DATAES-896
404408
public void shouldUseFieldNameOnMultiField() throws JSONException {
405409

406410
// given
407-
String expected = "{\"properties\":{" + "\"id-property\":{\"type\":\"keyword\",\"index\":true},"
408-
+ "\"multifield-property\":{\"type\":\"text\",\"analyzer\":\"whitespace\",\"fields\":{\"prefix\":{\"type\":\"text\",\"analyzer\":\"stop\",\"search_analyzer\":\"standard\"}}}}}";
411+
String expected = "{\n" + //
412+
" \"properties\": {\n" + //
413+
" \"id-property\": {\n" + //
414+
" \"type\": \"keyword\",\n" + //
415+
" \"index\": true\n" + //
416+
" },\n" + //
417+
" \"main-field\": {\n" + //
418+
" \"type\": \"text\",\n" + //
419+
" \"analyzer\": \"whitespace\",\n" + //
420+
" \"fields\": {\n" + //
421+
" \"suff-ix\": {\n" + //
422+
" \"type\": \"text\",\n" + //
423+
" \"analyzer\": \"stop\",\n" + //
424+
" \"search_analyzer\": \"standard\"\n" + //
425+
" }\n" + //
426+
" }\n" + //
427+
" }\n" + //
428+
" }\n" + //
429+
"}\n"; //
409430

410431
// when
411432
String mapping = getMappingBuilder().buildPropertyMapping(FieldNameEntity.MultiFieldEntity.class);
@@ -651,9 +672,10 @@ static class MultiFieldEntity {
651672

652673
@Nullable @Id @Field("id-property") private String id;
653674

654-
@Nullable @Field("multifield-property") //
655-
@MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"), otherFields = {
656-
@InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) //
675+
@Nullable //
676+
@MultiField(mainField = @Field(name = "main-field", type = FieldType.Text, analyzer = "whitespace"),
677+
otherFields = {
678+
@InnerField(suffix = "suff-ix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) //
657679
private String description;
658680
}
659681
}
@@ -684,6 +706,7 @@ static class Book {
684706
* @author Stuart Stevenson
685707
* @author Mohsin Husen
686708
*/
709+
@Data
687710
@Document(indexName = "test-index-simple-recursive-mapping-builder", replicas = 0, refreshInterval = "-1")
688711
static class SimpleRecursiveEntity {
689712

@@ -783,7 +806,7 @@ public void setMessage(String message) {
783806
*/
784807
static class SampleInheritedEntityBuilder {
785808

786-
private SampleInheritedEntity result;
809+
private final SampleInheritedEntity result;
787810

788811
public SampleInheritedEntityBuilder(String id) {
789812
result = new SampleInheritedEntity();
@@ -806,7 +829,7 @@ public SampleInheritedEntity build() {
806829

807830
public IndexQuery buildIndex() {
808831
IndexQuery indexQuery = new IndexQuery();
809-
indexQuery.setId(result.getId());
832+
indexQuery.setId(Objects.requireNonNull(result.getId()));
810833
indexQuery.setObject(result);
811834
return indexQuery;
812835
}
@@ -1030,7 +1053,7 @@ public String getValue() {
10301053

10311054
@Document(indexName = "valueDoc")
10321055
static class ValueDoc {
1033-
@Field(type = Text) private ValueObject valueObject;
1056+
@Nullable @Field(type = Text) private ValueObject valueObject;
10341057
}
10351058

10361059
@Getter

src/test/java/org/springframework/data/elasticsearch/core/index/MappingParametersTest.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.springframework.data.elasticsearch.annotations.Field;
99
import org.springframework.data.elasticsearch.annotations.FieldType;
1010
import org.springframework.data.elasticsearch.annotations.InnerField;
11+
import org.springframework.data.elasticsearch.annotations.MultiField;
1112
import org.springframework.data.elasticsearch.annotations.Score;
1213
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
1314
import org.springframework.lang.Nullable;
@@ -31,9 +32,10 @@ public void shouldCreateParametersForFieldAnnotation() {
3132

3233
@Test // DATAES-621
3334
public void shouldCreateParametersForInnerFieldAnnotation() {
34-
Annotation annotation = entity.getRequiredPersistentProperty("innerField").findAnnotation(InnerField.class);
3535

36-
MappingParameters mappingParameters = MappingParameters.from(annotation);
36+
MultiField multiField = entity.getRequiredPersistentProperty("mainField").findAnnotation(MultiField.class);
37+
InnerField innerField = multiField.otherFields()[0];
38+
MappingParameters mappingParameters = MappingParameters.from(innerField);
3739

3840
assertThat(mappingParameters).isNotNull();
3941
}
@@ -61,7 +63,8 @@ public void shouldNotAllowDocValuesFalseOnFieldTypeNested() {
6163

6264
static class AnnotatedClass {
6365
@Nullable @Field private String field;
64-
@Nullable @InnerField(suffix = "test", type = FieldType.Text) private String innerField;
66+
@Nullable @MultiField(mainField = @Field,
67+
otherFields = { @InnerField(suffix = "test", type = FieldType.Text) }) private String mainField;
6568
@Score private float score;
6669
@Nullable @Field(type = FieldType.Text, docValues = false) private String docValuesText;
6770
@Nullable @Field(type = FieldType.Nested, docValues = false) private String docValuesNested;

src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.springframework.data.elasticsearch.annotations.DateFormat;
2929
import org.springframework.data.elasticsearch.annotations.Field;
3030
import org.springframework.data.elasticsearch.annotations.FieldType;
31+
import org.springframework.data.elasticsearch.annotations.InnerField;
32+
import org.springframework.data.elasticsearch.annotations.MultiField;
3133
import org.springframework.data.elasticsearch.annotations.Score;
3234
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
3335
import org.springframework.data.mapping.MappingException;
@@ -74,6 +76,16 @@ public void fieldAnnotationWithValueSetsFieldname() {
7476
assertThat(persistentProperty.getFieldName()).isEqualTo("by-value");
7577
}
7678

79+
@Test // DATAES-896
80+
void shouldUseNameFromMultiFieldMainField() {
81+
SimpleElasticsearchPersistentEntity<?> persistentEntity = context
82+
.getRequiredPersistentEntity(MultiFieldProperty.class);
83+
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getPersistentProperty("mainfieldProperty");
84+
85+
assertThat(persistentProperty).isNotNull();
86+
assertThat(persistentProperty.getFieldName()).isEqualTo("mainfield");
87+
}
88+
7789
@Test // DATAES-716, DATAES-792
7890
void shouldSetPropertyConverters() {
7991
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
@@ -199,6 +211,11 @@ static class FieldValueProperty {
199211
@Nullable @Field(value = "by-value") String fieldProperty;
200212
}
201213

214+
static class MultiFieldProperty {
215+
@Nullable @MultiField(mainField = @Field("mainfield"),
216+
otherFields = { @InnerField(suffix = "suff", type = FieldType.Keyword) }) String mainfieldProperty;
217+
}
218+
202219
static class DatesProperty {
203220
@Nullable @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd.MM.uuuu") LocalDate localDate;
204221
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) LocalDateTime localDateTime;

0 commit comments

Comments
 (0)