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 0d7855c017..fb24e05483 100644 --- a/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java +++ b/src/main/java/org/springframework/data/elasticsearch/annotations/Document.java @@ -58,6 +58,13 @@ */ boolean createIndex() default true; + /** + * If true, the index mapping will be written on repository bootstrapping even when the index already exists. This + * allows for automatically updating the mapping with new properties. Changes on existing properties will lead to an + * error from the Elasticsearch server. + */ + boolean alwaysWriteMapping() default false; + /** * Configuration of version management. */ 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 c8a03d8b0f..15583fcd68 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 @@ -187,4 +187,10 @@ default ElasticsearchPersistentProperty getRequiredSeqNoPrimaryTermProperty() { * @since 5.1 */ boolean storeVersionInSource(); + + /** + * @return if the mapping should be written to the index on repositry bootstrap even if the index already exists. + * @since 5.2 + */ + boolean isAlwaysWriteMapping(); } 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 396f379afb..9c7df458ed 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 @@ -74,6 +74,7 @@ public class SimpleElasticsearchPersistentEntity extends BasicPersistentEntit private @Nullable ElasticsearchPersistentProperty indexedIndexNameProperty; private @Nullable Document.VersionType versionType; private boolean createIndexAndMapping; + private boolean alwaysWriteMapping; private final Dynamic dynamic; private final Map fieldNamePropertyCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap routingExpressions = new ConcurrentHashMap<>(); @@ -107,6 +108,7 @@ public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation, this.indexName = document.indexName(); this.versionType = document.versionType(); this.createIndexAndMapping = document.createIndex(); + this.alwaysWriteMapping = document.alwaysWriteMapping(); this.dynamic = document.dynamic(); this.storeIdInSource = document.storeIdInSource(); this.storeVersionInSource = document.storeVersionInSource(); @@ -114,6 +116,8 @@ public SimpleElasticsearchPersistentEntity(TypeInformation typeInformation, this.dynamic = Dynamic.INHERIT; this.storeIdInSource = true; this.storeVersionInSource = true; + this.createIndexAndMapping = false; + this.alwaysWriteMapping = false; } Routing routingAnnotation = AnnotatedElementUtils.findMergedAnnotation(clazz, Routing.class); @@ -172,6 +176,10 @@ public boolean isCreateIndexAndMapping() { return createIndexAndMapping; } + public boolean isAlwaysWriteMapping() { + return alwaysWriteMapping; + } + @Override public FieldNamingStrategy getFieldNamingStrategy() { return contextConfiguration.getFieldNamingStrategy(); diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java index 763929e351..e6673a76df 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleElasticsearchRepository.java @@ -82,6 +82,8 @@ public SimpleElasticsearchRepository(ElasticsearchEntityInformation metad if (shouldCreateIndexAndMapping() && !indexOperations.exists()) { indexOperations.createWithMapping(); + } else if (shouldAlwaysWriteMapping()) { + indexOperations.putMapping(); } } @@ -92,6 +94,11 @@ private boolean shouldCreateIndexAndMapping() { return entity.isCreateIndexAndMapping(); } + private boolean shouldAlwaysWriteMapping() { + return operations.getElasticsearchConverter().getMappingContext() + .getRequiredPersistentEntity(entityClass).isAlwaysWriteMapping(); + } + @Override public Optional findById(ID id) { return Optional.ofNullable( diff --git a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java index b0279e4cfe..30251ac6b4 100644 --- a/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java +++ b/src/main/java/org/springframework/data/elasticsearch/repository/support/SimpleReactiveElasticsearchRepository.java @@ -66,6 +66,8 @@ private void createIndexAndMappingIfNeeded() { indexOperations.exists() // .flatMap(exists -> exists ? Mono.empty() : indexOperations.createWithMapping()) // .block(); + } else if(shouldAlwaysWriteMapping()) { + indexOperations.putMapping().block(); } } @@ -76,6 +78,11 @@ private boolean shouldCreateIndexAndMapping() { return entity.isCreateIndexAndMapping(); } + private boolean shouldAlwaysWriteMapping() { + return operations.getElasticsearchConverter().getMappingContext() + .getRequiredPersistentEntity(entityInformation.getJavaType()).isAlwaysWriteMapping(); + } + @Override public Mono save(S entity) {