From e54c03d06a86dccd598412fb603ee3a85116f136 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Sun, 6 Feb 2022 11:35:32 +0100 Subject: [PATCH] Allow index names per query in bulk requests. Original Pull Request #2079 Closes #2043 --- .../elasticsearch/core/RequestFactory.java | 4 +- .../elasticsearch/core/query/IndexQuery.java | 12 ++- .../core/query/IndexQueryBuilder.java | 11 ++- .../elasticsearch/core/query/UpdateQuery.java | 20 +++- .../core/RequestFactoryTests.java | 94 ++++++++++++++++--- ...eriaQueryRestTemplateIntegrationTests.java | 2 +- ...epositoryRestTemplateIntegrationTests.java | 3 +- ...epositoryRestTemplateIntegrationTests.java | 3 +- 8 files changed, 126 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java index a55af3538..8468d46e0 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/RequestFactory.java @@ -600,7 +600,7 @@ class RequestFactory { // region indexing public IndexRequest indexRequest(IndexQuery query, IndexCoordinates index) { - String indexName = index.getIndexName(); + String indexName = query.getIndexName() != null ? query.getIndexName() : index.getIndexName(); IndexRequest indexRequest; Object queryObject = query.getObject(); @@ -1027,7 +1027,7 @@ class RequestFactory { // region update public UpdateRequest updateRequest(UpdateQuery query, IndexCoordinates index) { - String indexName = index.getIndexName(); + String indexName = query.getIndexName() != null ? query.getIndexName() : index.getIndexName(); UpdateRequest updateRequest = new UpdateRequest(indexName, query.getId()); if (query.getScript() != null) { diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java index 1b6607574..b0cacb8ed 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQuery.java @@ -38,12 +38,13 @@ public class IndexQuery { @Nullable private Long primaryTerm; @Nullable private String routing; @Nullable private OpType opType; + @Nullable private String indexName; public IndexQuery() {} public IndexQuery(@Nullable String id, @Nullable Object object, @Nullable Long version, @Nullable String source, @Nullable String parentId, @Nullable Long seqNo, @Nullable Long primaryTerm, @Nullable String routing, - @Nullable OpType opType) { + @Nullable OpType opType, @Nullable String indexName) { this.id = id; this.object = object; this.version = version; @@ -53,6 +54,7 @@ public class IndexQuery { this.primaryTerm = primaryTerm; this.routing = routing; this.opType = opType; + this.indexName = indexName; } @Nullable @@ -152,6 +154,14 @@ public class IndexQuery { this.opType = opType; } + /** + * @since 4.4 + */ + @Nullable + public String getIndexName() { + return indexName; + } + /** * OpType for the index operation. * diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQueryBuilder.java b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQueryBuilder.java index 4e0002e21..088da46d5 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQueryBuilder.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/IndexQueryBuilder.java @@ -40,6 +40,7 @@ public class IndexQueryBuilder { @Nullable private String routing; @Nullable private IndexQuery.OpType opType; @Nullable private RefreshPolicy refreshPolicy; + @Nullable private String indexName; public IndexQueryBuilder() {} @@ -89,6 +90,14 @@ public class IndexQueryBuilder { } public IndexQuery build() { - return new IndexQuery(id, object, version, source, parentId, seqNo, primaryTerm, routing, opType); + return new IndexQuery(id, object, version, source, parentId, seqNo, primaryTerm, routing, opType, indexName); + } + + /** + * @since 4.4 + */ + public IndexQueryBuilder withIndex(@Nullable String indexName) { + this.indexName = indexName; + return this; } } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/query/UpdateQuery.java b/src/main/java/org/springframework/data/elasticsearch/core/query/UpdateQuery.java index dd2c20510..d30e1ca72 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/query/UpdateQuery.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/query/UpdateQuery.java @@ -63,6 +63,7 @@ public class UpdateQuery { @Nullable private final Integer slices; @Nullable private final ScriptType scriptType; @Nullable private final String scriptName; + @Nullable private final String indexName; public static Builder builder(String id) { return new Builder(id); @@ -81,7 +82,7 @@ public class UpdateQuery { @Nullable Boolean abortOnVersionConflict, @Nullable Integer batchSize, @Nullable Integer maxDocs, @Nullable Integer maxRetries, @Nullable String pipeline, @Nullable Float requestsPerSecond, @Nullable Boolean shouldStoreResult, @Nullable Integer slices, @Nullable ScriptType scriptType, - @Nullable String scriptName) { + @Nullable String scriptName, @Nullable String indexName) { this.id = id; this.script = script; @@ -112,6 +113,7 @@ public class UpdateQuery { this.slices = slices; this.scriptType = scriptType; this.scriptName = scriptName; + this.indexName = indexName; } public String getId() { @@ -258,6 +260,14 @@ public class UpdateQuery { return scriptName; } + /** + * @since 4.4 + */ + @Nullable + public String getIndexName() { + return indexName; + } + public static final class Builder { private String id; @Nullable private String script = null; @@ -288,6 +298,7 @@ public class UpdateQuery { @Nullable private Integer slices; @Nullable private ScriptType scriptType; @Nullable private String scriptName; + @Nullable private String indexName; private Builder(String id) { this.id = id; @@ -441,7 +452,12 @@ public class UpdateQuery { return new UpdateQuery(id, script, params, document, upsert, lang, routing, scriptedUpsert, docAsUpsert, fetchSource, fetchSourceIncludes, fetchSourceExcludes, ifSeqNo, ifPrimaryTerm, refreshPolicy, retryOnConflict, timeout, waitForActiveShards, query, abortOnVersionConflict, batchSize, maxDocs, maxRetries, pipeline, - requestsPerSecond, shouldStoreResult, slices, scriptType, scriptName); + requestsPerSecond, shouldStoreResult, slices, scriptType, scriptName, indexName); + } + + public Builder withIndex(@Nullable String indexName) { + this.indexName = indexName; + return this; } } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/RequestFactoryTests.java b/src/test/java/org/springframework/data/elasticsearch/core/RequestFactoryTests.java index 3e61fe735..06a64aa3b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/RequestFactoryTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/RequestFactoryTests.java @@ -29,6 +29,7 @@ import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.indices.PutIndexTemplateRequest; import org.elasticsearch.common.lucene.search.function.CombineFunction; import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; @@ -57,12 +58,12 @@ import org.springframework.data.elasticsearch.core.index.AliasAction; import org.springframework.data.elasticsearch.core.index.AliasActionParameters; import org.springframework.data.elasticsearch.core.index.AliasActions; import org.springframework.data.elasticsearch.core.index.PutTemplateRequest; -import org.springframework.data.elasticsearch.core.reindex.ReindexRequest; -import org.springframework.data.elasticsearch.core.reindex.Remote; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.elasticsearch.core.query.*; import org.springframework.data.elasticsearch.core.query.RescorerQuery.ScoreMode; +import org.springframework.data.elasticsearch.core.reindex.ReindexRequest; +import org.springframework.data.elasticsearch.core.reindex.Remote; import org.springframework.lang.Nullable; /** @@ -92,7 +93,8 @@ class RequestFactoryTests { requestFactory = new RequestFactory((converter)); } - @Test // FPI-734 + @Test + // FPI-734 void shouldBuildSearchWithGeoSortSort() throws JSONException { CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith")); Sort sort = Sort.by(new GeoDistanceOrder("location", new GeoPoint(49.0, 8.4))); @@ -140,7 +142,8 @@ class RequestFactoryTests { assertEquals(expected, searchRequest, false); } - @Test // DATAES-449 + @Test + // DATAES-449 void shouldAddRouting() { String route = "route66"; CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith")); @@ -152,7 +155,8 @@ class RequestFactoryTests { assertThat(searchRequest.routing()).isEqualTo(route); } - @Test // DATAES-765 + @Test + // DATAES-765 void shouldAddMaxQueryWindowForUnpagedToRequest() { Query query = new NativeSearchQueryBuilder().withQuery(matchAllQuery()).withPageable(Pageable.unpaged()).build(); @@ -162,7 +166,8 @@ class RequestFactoryTests { assertThat(searchRequest.source().size()).isEqualTo(RequestFactory.INDEX_MAX_RESULT_WINDOW); } - @Test // DATAES-799 + @Test + // DATAES-799 void shouldIncludeSeqNoAndPrimaryTermFromIndexQueryToIndexRequest() { IndexQuery query = new IndexQuery(); query.setObject(new Person()); @@ -175,7 +180,8 @@ class RequestFactoryTests { assertThat(request.ifPrimaryTerm()).isEqualTo(2L); } - @Test // DATAES-799 + @Test + // DATAES-799 void shouldNotRequestSeqNoAndPrimaryTermWhenEntityClassDoesNotContainSeqNoPrimaryTermProperty() { Query query = new NativeSearchQueryBuilder().build(); @@ -184,7 +190,8 @@ class RequestFactoryTests { assertThat(request.source().seqNoAndPrimaryTerm()).isNull(); } - @Test // DATAES-799 + @Test + // DATAES-799 void shouldRequestSeqNoAndPrimaryTermWhenEntityClassContainsSeqNoPrimaryTermProperty() { Query query = new NativeSearchQueryBuilder().build(); @@ -194,7 +201,8 @@ class RequestFactoryTests { assertThat(request.source().seqNoAndPrimaryTerm()).isTrue(); } - @Test // DATAES-799 + @Test + // DATAES-799 void shouldNotRequestSeqNoAndPrimaryTermWhenEntityClassIsNull() { Query query = new NativeSearchQueryBuilder().build(); @@ -203,7 +211,8 @@ class RequestFactoryTests { assertThat(request.source().seqNoAndPrimaryTerm()).isNull(); } - @Test // DATAES-864 + @Test + // DATAES-864 void shouldBuildIndicesAliasRequest() throws IOException, JSONException { AliasActions aliasActions = new AliasActions(); @@ -316,7 +325,8 @@ class RequestFactoryTests { assertEquals(expected, json, false); } - @Test // DATAES-612 + @Test + // DATAES-612 void shouldCreatePutIndexTemplateRequest() throws JSONException, IOException { String expected = "{\n" + // @@ -430,7 +440,8 @@ class RequestFactoryTests { return XContentHelper.toXContent(request, XContentType.JSON, true).utf8ToString(); } - @Test // #1686 + @Test + // #1686 void shouldBuildSearchWithRescorerQuery() throws JSONException { CriteriaQuery query = new CriteriaQuery(new Criteria("lastName").is("Smith")); RescorerQuery rescorerQuery = new RescorerQuery(new NativeSearchQueryBuilder() // @@ -546,7 +557,7 @@ class RequestFactoryTests { assertThat(searchRequest.requestCache()).isFalse(); } - @Test + @Test // #2004 @DisplayName("should set stored fields on SearchRequest") void shouldSetStoredFieldsOnSearchRequest() { @@ -560,7 +571,8 @@ class RequestFactoryTests { .isEqualTo(Arrays.asList("last-name", "current-location")); } - @Test // #1529 + @Test + // #1529 void shouldCreateReindexRequest() throws IOException, JSONException { final String expected = "{\n" + // " \"source\":{\n" + // @@ -608,6 +620,7 @@ class RequestFactoryTests { } @Test + // #1529 void shouldAllowSourceQueryForReindexWithoutRemote() throws IOException, JSONException { final String expected = "{\n" + // " \"source\":{\n" + // @@ -644,6 +657,59 @@ class RequestFactoryTests { .isNotNull(); } + @Test // #2043 + @DisplayName("should use index name from query if set in bulk index") + void shouldUseIndexNameFromQueryIfSetInBulkIndex() { + + String queryIndexName = "query-index-name"; + String methodIndexName = "method-index-name"; + IndexQuery indexQuery = new IndexQueryBuilder().withIndex(queryIndexName).withId("42").withObject(new Person()) + .build(); + + IndexRequest indexRequest = requestFactory.indexRequest(indexQuery, IndexCoordinates.of(methodIndexName)); + + assertThat(indexRequest.index()).isEqualTo(queryIndexName); + } + + @Test // #2043 + @DisplayName("should use index name from method if none is set in query in bulk index") + void shouldUseIndexNameFromMethodIfNoneIsSetInQueryInBulkIndex() { + + String methodIndexName = "method-index-name"; + IndexQuery indexQuery = new IndexQueryBuilder().withId("42").withObject(new Person()).build(); + + IndexRequest indexRequest = requestFactory.indexRequest(indexQuery, IndexCoordinates.of(methodIndexName)); + + assertThat(indexRequest.index()).isEqualTo(methodIndexName); + } + + @Test // #2043 + @DisplayName("should use index name from query if set in bulk update") + void shouldUseIndexNameFromQueryIfSetInBulkUpdate() { + + String queryIndexName = "query-index-name"; + String methodIndexName = "method-index-name"; + UpdateQuery updateQuery = UpdateQuery.builder("42").withIndex(queryIndexName) + .withDocument(org.springframework.data.elasticsearch.core.document.Document.create()).build(); + + UpdateRequest updateRequest = requestFactory.updateRequest(updateQuery, IndexCoordinates.of(methodIndexName)); + + assertThat(updateRequest.index()).isEqualTo(queryIndexName); + } + + @Test // #2043 + @DisplayName("should use index name from method if none is set in query in bulk update") + void shouldUseIndexNameFromMethodIfNoneIsSetInQueryInBulkUpdate() { + + String methodIndexName = "method-index-name"; + UpdateQuery updateQuery = UpdateQuery.builder("42") + .withDocument(org.springframework.data.elasticsearch.core.document.Document.create()).build(); + + UpdateRequest updateRequest = requestFactory.updateRequest(updateQuery, IndexCoordinates.of(methodIndexName)); + + assertThat(updateRequest.index()).isEqualTo(methodIndexName); + } + // region entities static class Person { @Nullable diff --git a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryRestTemplateIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryRestTemplateIntegrationTests.java index 7c6e7229c..1ce806d50 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryRestTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/query/CriteriaQueryRestTemplateIntegrationTests.java @@ -33,7 +33,7 @@ public class CriteriaQueryRestTemplateIntegrationTests extends CriteriaQueryInte static class Config { @Bean IndexNameProvider indexNameProvider() { - return new IndexNameProvider(); + return new IndexNameProvider("criteria-query-es7"); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryRestTemplateIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryRestTemplateIntegrationTests.java index 9c50f428d..ccf349e60 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryRestTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/doubleid/DoubleIDRepositoryRestTemplateIntegrationTests.java @@ -28,13 +28,14 @@ import org.springframework.test.context.ContextConfiguration; */ @ContextConfiguration(classes = { DoubleIDRepositoryRestTemplateIntegrationTests.Config.class }) public class DoubleIDRepositoryRestTemplateIntegrationTests extends DoubleIDRepositoryIntegrationTests { + @Configuration @Import({ ElasticsearchRestTemplateConfiguration.class }) @EnableElasticsearchRepositories(considerNestedRepositories = true) static class Config { @Bean IndexNameProvider indexNameProvider() { - return new IndexNameProvider(); + return new IndexNameProvider("doubleid-reository-es7"); } } } diff --git a/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests.java index 03aefa94a..a3a2ddc34 100644 --- a/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/repositories/setting/dynamic/DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests.java @@ -29,13 +29,14 @@ import org.springframework.test.context.ContextConfiguration; @ContextConfiguration(classes = { DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests.Config.class }) public class DynamicSettingAndMappingEntityRepositoryRestTemplateIntegrationTests extends DynamicSettingAndMappingEntityRepositoryIntegrationTests { + @Configuration @Import({ ElasticsearchRestTemplateConfiguration.class }) @EnableElasticsearchRepositories(considerNestedRepositories = true) static class Config { @Bean IndexNameProvider indexNameProvider() { - return new IndexNameProvider(); + return new IndexNameProvider("dynamic-setting-and-mapping-3s7"); } }