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 97bbc186b..f37b047f1 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 @@ -349,8 +349,10 @@ private void buildPropertyMapping(ObjectNode propertiesNode, boolean isRootObjec : nestedPropertyPrefix + '.' + property.getFieldName(); Field fieldAnnotation = property.findAnnotation(Field.class); + MultiField multiFieldAnnotation = property.findAnnotation(MultiField.class); - if (fieldAnnotation != null && fieldAnnotation.excludeFromSource()) { + if ((fieldAnnotation != null && fieldAnnotation.excludeFromSource()) || + multiFieldAnnotation != null && multiFieldAnnotation.mainField().excludeFromSource()) { excludeFromSource.add(nestedPropertyPath); } @@ -381,8 +383,6 @@ private void buildPropertyMapping(ObjectNode propertiesNode, boolean isRootObjec } } - MultiField multiField = property.findAnnotation(MultiField.class); - if (isCompletionProperty) { CompletionField completionField = property.findAnnotation(CompletionField.class); applyCompletionFieldMapping(propertiesNode, property, completionField); @@ -390,8 +390,8 @@ private void buildPropertyMapping(ObjectNode propertiesNode, boolean isRootObjec if (isRootObject && fieldAnnotation != null && property.isIdProperty()) { applyDefaultIdFieldMapping(propertiesNode, property); - } else if (multiField != null) { - addMultiFieldMapping(propertiesNode, property, multiField, isNestedOrObjectProperty, dynamicMapping); + } else if (multiFieldAnnotation != null) { + addMultiFieldMapping(propertiesNode, property, multiFieldAnnotation, isNestedOrObjectProperty, dynamicMapping); } else if (fieldAnnotation != null) { addSingleFieldMapping(propertiesNode, property, fieldAnnotation, isNestedOrObjectProperty, dynamicMapping); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java index eb6f96b08..e79472d8f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderUnitTests.java @@ -1126,38 +1126,49 @@ void shouldAddFieldsThatAreExcludedFromSource() throws JSONException { String expected = """ { - "properties": { - "_class": { - "type": "keyword", - "index": false, - "doc_values": false - }, - "excluded-date": { - "type": "date", - "format": "date" - }, - "nestedEntity": { - "type": "nested", - "properties": { - "_class": { - "type": "keyword", - "index": false, - "doc_values": false - }, - "excluded-text": { - "type": "text" - } - } - } - }, - "_source": { - "excludes": [ - "excluded-date", - "nestedEntity.excluded-text" - ] - } - } - """; // + "properties": { + "_class": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "excluded-date": { + "type": "date", + "format": "date" + }, + "nestedEntity": { + "type": "nested", + "properties": { + "_class": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "excluded-text": { + "type": "text" + } + } + }, + "excluded-multifield": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword" + } + } + } + }, + "_source": { + "excludes": [ + "excluded-date", + "nestedEntity.excluded-text", + "excluded-multifield" + ] + } + + } + + """; // String mapping = getMappingBuilder().buildPropertyMapping(ExcludedFieldEntity.class); @@ -1243,7 +1254,7 @@ void shouldWriteFieldAliasesToTheMapping() throws JSONException { assertEquals(expected, mapping, true); } - + @Test // #2942 @DisplayName("should use custom mapped name") void shouldUseCustomMappedName() throws JSONException { @@ -2192,8 +2203,7 @@ static class DenseVectorEntityWithKnnSearch { @Nullable @Field(type = FieldType.Dense_Vector, dims = 16, elementType = FieldElementType.FLOAT, knnIndexOptions = @KnnIndexOptions(type = KnnAlgorithmType.HNSW, m = 16, efConstruction = 100), - knnSimilarity = KnnSimilarity.DOT_PRODUCT) - private float[] my_vector; + knnSimilarity = KnnSimilarity.DOT_PRODUCT) private float[] my_vector; @Nullable public String getId() { @@ -2269,8 +2279,7 @@ public void setText(@Nullable String text) { static class DenseVectorMisMatchConfidenceIntervalClass { @Field(type = Dense_Vector, dims = 16, elementType = FieldElementType.FLOAT, knnIndexOptions = @KnnIndexOptions(type = KnnAlgorithmType.HNSW, m = 16, confidenceInterval = 0.95F), - knnSimilarity = KnnSimilarity.DOT_PRODUCT) - private float[] dense_vector; + knnSimilarity = KnnSimilarity.DOT_PRODUCT) private float[] dense_vector; } static class DisabledMappingProperty { @@ -2553,6 +2562,10 @@ private static class ExcludedFieldEntity { excludeFromSource = true) private LocalDate excludedDate; @Nullable @Field(type = Nested) private NestedExcludedFieldEntity nestedEntity; + @Nullable + @MultiField(mainField = @Field(name = "excluded-multifield", type = Text, excludeFromSource = true), otherFields = { + @InnerField(suffix = "keyword", type = Keyword) + }) private String excludedMultifield; } @SuppressWarnings("unused") @@ -2599,8 +2612,10 @@ private static class FieldMappedNameEntity { @SuppressWarnings("unused") private static class MultiFieldMappedNameEntity { @Nullable - @MultiField(mainField = @Field(type = FieldType.Text, mappedTypeName = "match_only_text"), otherFields = { @InnerField(suffix = "lower_case", - type = FieldType.Keyword, normalizer = "lower_case_normalizer", mappedTypeName = "constant_keyword") }) private String description; + @MultiField(mainField = @Field(type = FieldType.Text, mappedTypeName = "match_only_text"), + otherFields = { @InnerField(suffix = "lower_case", + type = FieldType.Keyword, normalizer = "lower_case_normalizer", + mappedTypeName = "constant_keyword") }) private String description; } @SuppressWarnings("unused")