From fd23c10c163e1959362c078fd8fa4b812ce11c01 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Sun, 9 Aug 2020 16:28:35 +0200 Subject: [PATCH] DATAES-896 - Use mainField property of @MultiField annotation. Original PR: #500 --- .../elasticsearch/annotations/InnerField.java | 2 +- .../core/index/MappingBuilder.java | 8 ++-- ...SimpleElasticsearchPersistentProperty.java | 15 +++++-- .../core/index/MappingBuilderTests.java | 41 +++++++++++++++---- .../core/index/MappingParametersTest.java | 9 ++-- ...sticsearchPersistentPropertyUnitTests.java | 17 ++++++++ 6 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java index 05edbea2f..3f6fcb281 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/InnerField.java @@ -29,7 +29,7 @@ import java.lang.annotation.Target; * @author Aleksei Arsenev */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) +@Target(ElementType.ANNOTATION_TYPE) public @interface InnerField { String suffix(); diff --git a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java index 2bc5a5b31..8f48c0d85 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/index/MappingBuilder.java @@ -133,8 +133,8 @@ public class MappingBuilder { } } - private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, boolean isRootObject, - String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, + private void mapEntity(XContentBuilder builder, @Nullable ElasticsearchPersistentEntity entity, + boolean isRootObject, String nestedObjectFieldName, boolean nestedOrObjectField, FieldType fieldType, @Nullable Field parentFieldAnnotation, @Nullable DynamicMapping dynamicMapping) throws IOException { boolean writeNestedProperties = !isRootObject && (isAnyPropertyAnnotatedWithField(entity) || nestedOrObjectField); @@ -146,7 +146,7 @@ public class MappingBuilder { if (nestedOrObjectField && FieldType.Nested == fieldType && parentFieldAnnotation != null && parentFieldAnnotation.includeInParent()) { - builder.field("include_in_parent", parentFieldAnnotation.includeInParent()); + builder.field("include_in_parent", true); } } @@ -396,7 +396,7 @@ public class MappingBuilder { MappingParameters mappingParameters = MappingParameters.from(annotation); if (!nestedOrObjectField && mappingParameters.isStore()) { - builder.field(FIELD_PARAM_STORE, mappingParameters.isStore()); + builder.field(FIELD_PARAM_STORE, true); } mappingParameters.writeTypeAndParametersTo(builder); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java index a15fa56c6..7c3218acc 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java @@ -26,6 +26,7 @@ import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; +import org.springframework.data.elasticsearch.annotations.MultiField; import org.springframework.data.elasticsearch.annotations.Parent; import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter; @@ -97,6 +98,10 @@ public class SimpleElasticsearchPersistentProperty extends throw new MappingException(String.format("Parent property %s must be of type String!", property.getName())); } + if (isAnnotationPresent(Field.class) && isAnnotationPresent(MultiField.class)) { + throw new MappingException("@Field annotation must not be used on a @MultiField property."); + } + initDateConverter(); } @@ -182,13 +187,15 @@ public class SimpleElasticsearchPersistentProperty extends @Nullable private String getAnnotatedFieldName() { - if (isAnnotationPresent(Field.class)) { + String name = null; - String name = findAnnotation(Field.class).name(); - return StringUtils.hasText(name) ? name : null; + if (isAnnotationPresent(Field.class)) { + name = findAnnotation(Field.class).name(); + } else if (isAnnotationPresent(MultiField.class)) { + name = findAnnotation(MultiField.class).mainField().name(); } - return null; + return StringUtils.hasText(name) ? name : null; } /* diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java index 61426d849..64ff01fdb 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderTests.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.assertj.core.data.Percentage; @@ -255,6 +256,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { } @Test // DATAES-420 + @SuppressWarnings({ "rawtypes", "unchecked" }) public void shouldUseBothAnalyzer() { // given @@ -277,6 +279,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { } @Test // DATAES-492 + @SuppressWarnings("rawtypes") public void shouldUseKeywordNormalizer() { // given @@ -297,6 +300,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { } @Test // DATAES-503 + @SuppressWarnings("rawtypes") public void shouldUseCopyTo() { // given @@ -400,12 +404,29 @@ public class MappingBuilderTests extends MappingContextBaseTests { assertEquals(expected, mapping, false); } - @Test // DATAES-568 + @Test // DATAES-568, DATAES-896 public void shouldUseFieldNameOnMultiField() throws JSONException { // given - String expected = "{\"properties\":{" + "\"id-property\":{\"type\":\"keyword\",\"index\":true}," - + "\"multifield-property\":{\"type\":\"text\",\"analyzer\":\"whitespace\",\"fields\":{\"prefix\":{\"type\":\"text\",\"analyzer\":\"stop\",\"search_analyzer\":\"standard\"}}}}}"; + String expected = "{\n" + // + " \"properties\": {\n" + // + " \"id-property\": {\n" + // + " \"type\": \"keyword\",\n" + // + " \"index\": true\n" + // + " },\n" + // + " \"main-field\": {\n" + // + " \"type\": \"text\",\n" + // + " \"analyzer\": \"whitespace\",\n" + // + " \"fields\": {\n" + // + " \"suff-ix\": {\n" + // + " \"type\": \"text\",\n" + // + " \"analyzer\": \"stop\",\n" + // + " \"search_analyzer\": \"standard\"\n" + // + " }\n" + // + " }\n" + // + " }\n" + // + " }\n" + // + "}\n"; // // when String mapping = getMappingBuilder().buildPropertyMapping(FieldNameEntity.MultiFieldEntity.class); @@ -651,9 +672,10 @@ public class MappingBuilderTests extends MappingContextBaseTests { @Nullable @Id @Field("id-property") private String id; - @Nullable @Field("multifield-property") // - @MultiField(mainField = @Field(type = FieldType.Text, analyzer = "whitespace"), otherFields = { - @InnerField(suffix = "prefix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) // + @Nullable // + @MultiField(mainField = @Field(name = "main-field", type = FieldType.Text, analyzer = "whitespace"), + otherFields = { + @InnerField(suffix = "suff-ix", type = FieldType.Text, analyzer = "stop", searchAnalyzer = "standard") }) // private String description; } } @@ -684,6 +706,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { * @author Stuart Stevenson * @author Mohsin Husen */ + @Data @Document(indexName = "test-index-simple-recursive-mapping-builder", replicas = 0, refreshInterval = "-1") static class SimpleRecursiveEntity { @@ -783,7 +806,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { */ static class SampleInheritedEntityBuilder { - private SampleInheritedEntity result; + private final SampleInheritedEntity result; public SampleInheritedEntityBuilder(String id) { result = new SampleInheritedEntity(); @@ -806,7 +829,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { public IndexQuery buildIndex() { IndexQuery indexQuery = new IndexQuery(); - indexQuery.setId(result.getId()); + indexQuery.setId(Objects.requireNonNull(result.getId())); indexQuery.setObject(result); return indexQuery; } @@ -1030,7 +1053,7 @@ public class MappingBuilderTests extends MappingContextBaseTests { @Document(indexName = "valueDoc") static class ValueDoc { - @Field(type = Text) private ValueObject valueObject; + @Nullable @Field(type = Text) private ValueObject valueObject; } @Getter diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingParametersTest.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingParametersTest.java index f12c8e541..ffce29eec 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingParametersTest.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingParametersTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; 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; import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity; import org.springframework.lang.Nullable; @@ -31,9 +32,10 @@ public class MappingParametersTest extends MappingContextBaseTests { @Test // DATAES-621 public void shouldCreateParametersForInnerFieldAnnotation() { - Annotation annotation = entity.getRequiredPersistentProperty("innerField").findAnnotation(InnerField.class); - MappingParameters mappingParameters = MappingParameters.from(annotation); + MultiField multiField = entity.getRequiredPersistentProperty("mainField").findAnnotation(MultiField.class); + InnerField innerField = multiField.otherFields()[0]; + MappingParameters mappingParameters = MappingParameters.from(innerField); assertThat(mappingParameters).isNotNull(); } @@ -61,7 +63,8 @@ public class MappingParametersTest extends MappingContextBaseTests { static class AnnotatedClass { @Nullable @Field private String field; - @Nullable @InnerField(suffix = "test", type = FieldType.Text) private String innerField; + @Nullable @MultiField(mainField = @Field, + otherFields = { @InnerField(suffix = "test", type = FieldType.Text) }) private String mainField; @Score private float score; @Nullable @Field(type = FieldType.Text, docValues = false) private String docValuesText; @Nullable @Field(type = FieldType.Nested, docValues = false) private String docValuesNested; diff --git a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java index 3d6dec9e0..186f3792b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentPropertyUnitTests.java @@ -28,6 +28,8 @@ import org.junit.jupiter.api.Test; import org.springframework.data.elasticsearch.annotations.DateFormat; 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; import org.springframework.data.elasticsearch.annotations.Score; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; import org.springframework.data.mapping.MappingException; @@ -74,6 +76,16 @@ public class SimpleElasticsearchPersistentPropertyUnitTests { assertThat(persistentProperty.getFieldName()).isEqualTo("by-value"); } + @Test // DATAES-896 + void shouldUseNameFromMultiFieldMainField() { + SimpleElasticsearchPersistentEntity persistentEntity = context + .getRequiredPersistentEntity(MultiFieldProperty.class); + ElasticsearchPersistentProperty persistentProperty = persistentEntity.getPersistentProperty("mainfieldProperty"); + + assertThat(persistentProperty).isNotNull(); + assertThat(persistentProperty.getFieldName()).isEqualTo("mainfield"); + } + @Test // DATAES-716, DATAES-792 void shouldSetPropertyConverters() { SimpleElasticsearchPersistentEntity persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class); @@ -199,6 +211,11 @@ public class SimpleElasticsearchPersistentPropertyUnitTests { @Nullable @Field(value = "by-value") String fieldProperty; } + static class MultiFieldProperty { + @Nullable @MultiField(mainField = @Field("mainfield"), + otherFields = { @InnerField(suffix = "suff", type = FieldType.Keyword) }) String mainfieldProperty; + } + static class DatesProperty { @Nullable @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd.MM.uuuu") LocalDate localDate; @Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) LocalDateTime localDateTime;