diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java index e219ffaf2..47e55867f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java @@ -1419,7 +1419,7 @@ public Object get(ElasticsearchPersistentProperty property) { } - if (!fieldName.contains(".")) { + if (property.hasExplicitFieldName() || !fieldName.contains(".")) { return target.get(fieldName); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java index f82353892..e8aa672db 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java @@ -39,6 +39,12 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty mapToNotWrit this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty; } } + static class FieldNameDotsEntity { + @Id + @Nullable private String id; + @Nullable + @Field(name = "dotted.field", type = FieldType.Text) private String dottedField; + + @Nullable + public String getId() { + return id; + } + + public void setId(@Nullable String id) { + this.id = id; + } + + @Nullable + public String getDottedField() { + return dottedField; + } + + public void setDottedField(@Nullable String dottedField) { + this.dottedField = dottedField; + } + } + // endregion private static String reverse(Object o) { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java index 3f3912b20..5d7c4670e 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/index/MappingBuilderIntegrationTests.java @@ -279,6 +279,14 @@ void shouldWriteSourceExcludes() { indexOps.createWithMapping(); } + @Test // #2502 + @DisplayName(" should write mapping with field name with dots") + void shouldWriteMappingWithFieldNameWithDots() { + + IndexOperations indexOps = operations.indexOps(FieldNameDotsEntity.class); + indexOps.createWithMapping(); + } + // region Entities @Document(indexName = "#{@indexNameProvider.indexName()}") static class Book { @@ -901,5 +909,12 @@ private static class EntityWithAllTypes { @Nullable @Field(type = FieldType.Dense_Vector, dims = 1) String denseVectorField; } + @Document(indexName = "#{@indexNameProvider.indexName()}") + private static class FieldNameDotsEntity { + @Id + @Nullable private String id; + @Nullable + @Field(name = "dotted.field", type = Text) private String dottedField; + } // endregion } 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 11d256f91..c931a3ffb 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 @@ -1065,6 +1065,30 @@ void shouldNotWriteMappingForPropertyWithIndexedIndexNameAnotation() throws JSON assertEquals(expected, mapping, true); } + + @Test // #2502 + @DisplayName("should use custom name with dots") + void shouldUseCustomNameWithDots() throws JSONException { + + var expected = """ + { + "properties": { + "_class": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "dotted.field": { + "type": "text" + } + } + } + """; + String mapping = getMappingBuilder().buildPropertyMapping(FieldNameDotsEntity.class); + + assertEquals(expected, mapping, true); + } + // region entities @Document(indexName = "ignore-above-index") @@ -2220,8 +2244,14 @@ private static class IndexedIndexNameEntity { @Nullable @Field(type = Text) private String someText; @Nullable - @IndexedIndexName - private String storedIndexName; + @IndexedIndexName private String storedIndexName; + } + + private static class FieldNameDotsEntity { + @Id + @Nullable private String id; + @Nullable + @Field(name = "dotted.field", type = Text) private String dottedField; } // endregion }