diff --git a/pom.xml b/pom.xml index 0e19b3788..4be105416 100644 --- a/pom.xml +++ b/pom.xml @@ -452,7 +452,7 @@ integration-test - org.springframework.data.elasticsearch.core.geo.* + org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter* toString diff --git a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java index fa84ec8dc..f64335842 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java @@ -77,6 +77,14 @@ */ Dynamic dynamic() default Dynamic.INHERIT; + /** + * Specifies if the id property should also be stored in the Elasticsearch document source. Default value is + * {@literal true} + * + * @since 5.1 + */ + boolean storeIdInSource() default true; + /** * @since 4.3 */ 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 0562dd180..e1513b454 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 @@ -939,7 +939,13 @@ private void writeProperties(ElasticsearchPersistentEntity entity, Persistent for (ElasticsearchPersistentProperty property : entity) { - if (!property.isWritable() || property.isIndexedIndexNameProperty()) { + if (!property.isWritable() // + || property.isIndexedIndexNameProperty() // + || (property.isIdProperty() && !entity.storeIdInSource())) { + continue; + } + + if (property.isIdProperty() && !entity.storeIdInSource()) { continue; } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java index 86ec740eb..ae21d3a35 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentEntity.java @@ -175,4 +175,10 @@ default ElasticsearchPersistentProperty getRequiredSeqNoPrimaryTermProperty() { * @since 4.3 */ Dynamic dynamic(); + + /** + * @return the storeIdInSource value from the document annotation + * @since 5.1 + */ + boolean storeIdInSource(); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java index af1c34adb..7b33291e5 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentEntity.java @@ -27,7 +27,6 @@ import org.springframework.data.elasticsearch.annotations.Dynamic; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; -import org.springframework.data.elasticsearch.annotations.IndexedIndexName; import org.springframework.data.elasticsearch.annotations.Routing; import org.springframework.data.elasticsearch.annotations.Setting; import org.springframework.data.elasticsearch.core.index.Settings; @@ -84,6 +83,8 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit private final ConcurrentHashMap indexNameExpressions = new ConcurrentHashMap<>(); private final Lazy indexNameEvaluationContext = Lazy.of(this::getIndexNameEvaluationContext); + private final boolean storeIdInSource; + public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation, ContextConfiguration contextConfiguration) { @@ -106,8 +107,10 @@ public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation, this.versionType = document.versionType(); this.createIndexAndMapping = document.createIndex(); this.dynamic = document.dynamic(); + this.storeIdInSource = document.storeIdInSource(); } else { this.dynamic = Dynamic.INHERIT; + this.storeIdInSource = true; } Routing routingAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Routing.class); @@ -192,6 +195,11 @@ public boolean writeTypeHints() { return writeTypeHints; } + @Override + public boolean storeIdInSource() { + return storeIdInSource; + } + @Override public void addPersistentProperty(ElasticsearchPersistentProperty property) { super.addPersistentProperty(property); diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java index 85798809a..43599f0db 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java @@ -1871,6 +1871,28 @@ private Map writeToMap(Object source) { return sink; } + @Test // #2364 + @DisplayName("should not write id property to document source if configured so") + void shouldNotWriteIdPropertyToDocumentSourceIfConfiguredSo() throws JSONException { + + @Language("JSON") + var expected = """ + { + "_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$DontWriteIdToSourceEntity", + "text": "some text" + } + """; + var entity = new DontWriteIdToSourceEntity(); + entity.setId("42"); + entity.setText("some text"); + + Document document = Document.create(); + mappingElasticsearchConverter.write(entity, document); + String json = document.toJson(); + + assertEquals(expected, json, true); + } + // region entities public static class Sample { @Nullable public @ReadOnlyProperty String readOnly; @@ -2885,7 +2907,7 @@ private static final class ImmutableEntityWithCollections { @Nullable private Set childrenSet; public ImmutableEntityWithCollections(@Nullable List stringList, @Nullable Set stringSet, - @Nullable List childrenList, @Nullable Set childrenSet) { + @Nullable List childrenList, @Nullable Set childrenSet) { this.stringList = stringList; this.stringSet = stringSet; this.childrenList = childrenList; @@ -2927,6 +2949,31 @@ public String getName() { } } } + + @org.springframework.data.elasticsearch.annotations.Document(indexName = "doesnt-matter", storeIdInSource = false) + static class DontWriteIdToSourceEntity { + @Nullable private String id; + @Nullable + @Field(type = FieldType.Text) private String text; + + @Nullable + public String getId() { + return id; + } + + public void setId(@Nullable String id) { + this.id = id; + } + + @Nullable + public String getText() { + return text; + } + + public void setText(@Nullable String text) { + this.text = text; + } + } // endregion private static String reverse(Object o) {