diff --git a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc index 756b39ca1..58bb48f10 100644 --- a/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc +++ b/src/main/asciidoc/reference/elasticsearch-migration-guide-4.1-4.2.adoc @@ -53,3 +53,10 @@ Previously the reactive code initialized this to `IMMEDIATE`, now reactive and n ==== delete methods that take a Query The reactive methods previously returned a `Mono` with the number of deleted documents, the non reactive versions were void. They now return a `Mono` which contains much more detailed information about the deleted documents and errors that might have occurred. + +==== multiget methods + +The implementations of _multiget_ previousl only returned the found entities in a `List` for non-reactive implementations and in a `Flux` for reactive implementations. If the request contained ids that were not found, the information that these are missing was not available. The user needed to compare the returned ids to the requested ones to find +which ones were missing. + +Now the `multiget` methods return a `MultiGetItem` for every requested id. This contains information about failures (like non existing indices) and the information if the item existed (then it is contained in the `MultiGetItem) or not. diff --git a/src/main/java/org/springframework/data/elasticsearch/client/reactive/DefaultReactiveElasticsearchClient.java b/src/main/java/org/springframework/data/elasticsearch/client/reactive/DefaultReactiveElasticsearchClient.java index e98d9647a..ce3ab80c7 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/reactive/DefaultReactiveElasticsearchClient.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/reactive/DefaultReactiveElasticsearchClient.java @@ -22,6 +22,7 @@ import io.netty.handler.ssl.JdkSslContext; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; +import org.elasticsearch.action.get.MultiGetItemResponse; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.netty.http.client.HttpClient; @@ -330,18 +331,12 @@ public Mono get(HttpHeaders headers, GetRequest getRequest) { .next(); } - /* - * (non-Javadoc) - * @see org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient#multiGet(org.springframework.http.HttpHeaders, org.elasticsearch.action.get.MultiGetRequest) - */ @Override - public Flux multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest) { + public Flux multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest) { return sendRequest(multiGetRequest, requestCreator.multiGet(), MultiGetResponse.class, headers) .map(MultiGetResponse::getResponses) // - .flatMap(Flux::fromArray) // - .filter(it -> !it.isFailed() && it.getResponse().isExists()) // - .map(it -> DefaultReactiveElasticsearchClient.getResponseToGetResult(it.getResponse())); + .flatMap(Flux::fromArray); // } /* diff --git a/src/main/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClient.java b/src/main/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClient.java index 1d1cca41d..dcc430758 100644 --- a/src/main/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClient.java +++ b/src/main/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClient.java @@ -15,11 +15,6 @@ */ package org.springframework.data.elasticsearch.client.reactive; -import org.elasticsearch.client.indices.CreateIndexRequest; -import org.elasticsearch.client.indices.GetIndexRequest; -import org.elasticsearch.client.indices.GetMappingsRequest; -import org.elasticsearch.client.indices.GetMappingsResponse; -import org.elasticsearch.client.indices.PutMappingRequest; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -42,6 +37,7 @@ import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetRequest; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; @@ -51,13 +47,7 @@ import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.GetAliasesResponse; -import org.elasticsearch.client.indices.GetFieldMappingsRequest; -import org.elasticsearch.client.indices.GetFieldMappingsResponse; -import org.elasticsearch.client.indices.GetIndexResponse; -import org.elasticsearch.client.indices.GetIndexTemplatesRequest; -import org.elasticsearch.client.indices.GetIndexTemplatesResponse; -import org.elasticsearch.client.indices.IndexTemplatesExistRequest; -import org.elasticsearch.client.indices.PutIndexTemplateRequest; +import org.elasticsearch.client.indices.*; import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.reindex.BulkByScrollResponse; import org.elasticsearch.index.reindex.DeleteByQueryRequest; @@ -167,9 +157,9 @@ default Mono get(GetRequest getRequest) { * @param consumer never {@literal null}. * @see Multi Get API on * elastic.co - * @return the {@link Flux} emitting the {@link GetResult result}. + * @return the {@link Flux} emitting the {@link MultiGetItemResponse result}. */ - default Flux multiGet(Consumer consumer) { + default Flux multiGet(Consumer consumer) { MultiGetRequest request = new MultiGetRequest(); consumer.accept(request); @@ -183,9 +173,9 @@ default Flux multiGet(Consumer consumer) { * @param multiGetRequest must not be {@literal null}. * @see Multi Get API on * elastic.co - * @return the {@link Flux} emitting the {@link GetResult result}. + * @return the {@link Flux} emitting the {@link MultiGetItemResponse result}. */ - default Flux multiGet(MultiGetRequest multiGetRequest) { + default Flux multiGet(MultiGetRequest multiGetRequest) { return multiGet(HttpHeaders.EMPTY, multiGetRequest); } @@ -197,9 +187,9 @@ default Flux multiGet(MultiGetRequest multiGetRequest) { * @param multiGetRequest must not be {@literal null}. * @see Multi Get API on * elastic.co - * @return the {@link Flux} emitting the {@link GetResult result}. + * @return the {@link Flux} emitting the {@link MultiGetItemResponse result}. */ - Flux multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest); + Flux multiGet(HttpHeaders headers, MultiGetRequest multiGetRequest); /** * Checks for the existence of a document. Emits {@literal true} if it exists, {@literal false} otherwise. @@ -748,31 +738,32 @@ default boolean isOk() { interface Indices { /** - * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the + * {@literal indices} API. * * @param consumer never {@literal null}. * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. * @see Indices * Exists API on elastic.co - * @deprecated since 4.2 + * @deprecated since 4.2 */ @Deprecated default Mono existsIndex(Consumer consumer) { - org.elasticsearch.action.admin.indices.get.GetIndexRequest request = - new org.elasticsearch.action.admin.indices.get.GetIndexRequest(); + org.elasticsearch.action.admin.indices.get.GetIndexRequest request = new org.elasticsearch.action.admin.indices.get.GetIndexRequest(); consumer.accept(request); return existsIndex(request); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the + * {@literal indices} API. * * @param getIndexRequest must not be {@literal null}. * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. * @see Indices * Exists API on elastic.co - * @deprecated since 4.2, use {@link #existsIndex(GetIndexRequest)} + * @deprecated since 4.2, use {@link #existsIndex(GetIndexRequest)} */ @Deprecated default Mono existsIndex(org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest) { @@ -780,42 +771,44 @@ default Mono existsIndex(org.elasticsearch.action.admin.indices.get.Get } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.get.GetIndexRequest} against the + * {@literal indices} API. * * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. * @param getIndexRequest must not be {@literal null}. * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. * @see Indices * Exists API on elastic.co - * @deprecated since 4.2, use {@link #existsIndex(HttpHeaders, GetIndexRequest)} + * @deprecated since 4.2, use {@link #existsIndex(HttpHeaders, GetIndexRequest)} */ @Deprecated - Mono existsIndex(HttpHeaders headers, org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest); - - /** - * Execute the given {@link GetIndexRequest} against the {@literal indices} API. - * - * @param getIndexRequest must not be {@literal null}. - * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. - * @see Indices - * Exists API on elastic.co - * @since 4.2 - */ - default Mono existsIndex(GetIndexRequest getIndexRequest) { - return existsIndex(HttpHeaders.EMPTY, getIndexRequest); - } - - /** - * Execute the given {@link GetIndexRequest} against the {@literal indices} API. - * - * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. - * @param getIndexRequest must not be {@literal null}. - * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. - * @see Indices - * Exists API on elastic.co - * @since 4.2 - */ - Mono existsIndex(HttpHeaders headers, GetIndexRequest getIndexRequest); + Mono existsIndex(HttpHeaders headers, + org.elasticsearch.action.admin.indices.get.GetIndexRequest getIndexRequest); + + /** + * Execute the given {@link GetIndexRequest} against the {@literal indices} API. + * + * @param getIndexRequest must not be {@literal null}. + * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. + * @see Indices + * Exists API on elastic.co + * @since 4.2 + */ + default Mono existsIndex(GetIndexRequest getIndexRequest) { + return existsIndex(HttpHeaders.EMPTY, getIndexRequest); + } + + /** + * Execute the given {@link GetIndexRequest} against the {@literal indices} API. + * + * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. + * @param getIndexRequest must not be {@literal null}. + * @return the {@link Mono} emitting {@literal true} if the index exists, {@literal false} otherwise. + * @see Indices + * Exists API on elastic.co + * @since 4.2 + */ + Mono existsIndex(HttpHeaders headers, GetIndexRequest getIndexRequest); /** * Execute the given {@link DeleteIndexRequest} against the {@literal indices} API. @@ -859,7 +852,8 @@ default Mono deleteIndex(DeleteIndexRequest deleteIndexRequest) { Mono deleteIndex(HttpHeaders headers, DeleteIndexRequest deleteIndexRequest); /** - * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the + * {@literal indices} API. * * @param consumer never {@literal null}. * @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if @@ -869,16 +863,17 @@ default Mono deleteIndex(DeleteIndexRequest deleteIndexRequest) { * @deprecated since 4.2 */ @Deprecated - default Mono createIndex(Consumer consumer) { + default Mono createIndex( + Consumer consumer) { - org.elasticsearch.action.admin.indices.create.CreateIndexRequest request = - new org.elasticsearch.action.admin.indices.create.CreateIndexRequest(); + org.elasticsearch.action.admin.indices.create.CreateIndexRequest request = new org.elasticsearch.action.admin.indices.create.CreateIndexRequest(); consumer.accept(request); return createIndex(request); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the + * {@literal indices} API. * * @param createIndexRequest must not be {@literal null}. * @return a {@link Mono} signalling successful operation completion or an {@link Mono#error(Throwable) error} if @@ -888,12 +883,14 @@ default Mono createIndex(Consumer createIndex(org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest) { + default Mono createIndex( + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest) { return createIndex(HttpHeaders.EMPTY, createIndexRequest); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.create.CreateIndexRequest} against the + * {@literal indices} API. * * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. * @param createIndexRequest must not be {@literal null}. @@ -904,7 +901,8 @@ default Mono createIndex(org.elasticsearch.action.admin.indices.create. * @deprecated since 4.2, use {@link #createIndex(HttpHeaders, CreateIndexRequest)} */ @Deprecated - Mono createIndex(HttpHeaders headers, org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest); + Mono createIndex(HttpHeaders headers, + org.elasticsearch.action.admin.indices.create.CreateIndexRequest createIndexRequest); /** * Execute the given {@link CreateIndexRequest} against the {@literal indices} API. @@ -1057,7 +1055,8 @@ default Mono refreshIndex(RefreshRequest refreshRequest) { Mono refreshIndex(HttpHeaders headers, RefreshRequest refreshRequest); /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param consumer never {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1067,12 +1066,14 @@ default Mono refreshIndex(RefreshRequest refreshRequest) { * @deprecated since 4.1, use {@link #putMapping(Consumer)} */ @Deprecated - default Mono updateMapping(Consumer consumer) { + default Mono updateMapping( + Consumer consumer) { return putMapping(consumer); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param putMappingRequest must not be {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1082,12 +1083,14 @@ default Mono updateMapping(Consumer updateMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { + default Mono updateMapping( + org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { return putMapping(putMappingRequest); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. * @param putMappingRequest must not be {@literal null}. @@ -1098,12 +1101,14 @@ default Mono updateMapping(org.elasticsearch.action.admin.indices.mappi * @deprecated since 4.1, use {@link #putMapping(HttpHeaders, PutMappingRequest)} */ @Deprecated - default Mono updateMapping(HttpHeaders headers, org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { + default Mono updateMapping(HttpHeaders headers, + org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { return putMapping(headers, putMappingRequest); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param consumer never {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1113,16 +1118,17 @@ default Mono updateMapping(HttpHeaders headers, org.elasticsearch.actio * @deprecated since 4.2 */ @Deprecated - default Mono putMapping(Consumer consumer) { + default Mono putMapping( + Consumer consumer) { - org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest request = - new org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest(); + org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest request = new org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest(); consumer.accept(request); return putMapping(request); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param putMappingRequest must not be {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1132,12 +1138,14 @@ default Mono putMapping(Consumer putMapping(org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { + default Mono putMapping( + org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest) { return putMapping(HttpHeaders.EMPTY, putMappingRequest); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} against the + * {@literal indices} API. * * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. * @param putMappingRequest must not be {@literal null}. @@ -1148,7 +1156,8 @@ default Mono putMapping(org.elasticsearch.action.admin.indices.mapping. * @deprecated since 4.2, use {@link #putMapping(HttpHeaders, PutMappingRequest)} */ @Deprecated - Mono putMapping(HttpHeaders headers, org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest); + Mono putMapping(HttpHeaders headers, + org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest putMappingRequest); /** * Execute the given {@link PutMappingRequest} against the {@literal indices} API. @@ -1263,7 +1272,8 @@ default Mono getSettings(GetSettingsRequest getSettingsRequ Mono getSettings(HttpHeaders headers, GetSettingsRequest getSettingsRequest); /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the + * {@literal indices} API. * * @param consumer never {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1275,16 +1285,16 @@ default Mono getSettings(GetSettingsRequest getSettingsRequ */ @Deprecated default Mono getMapping( - Consumer consumer) { + Consumer consumer) { - org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest request = - new org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest(); + org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest request = new org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest(); consumer.accept(request); return getMapping(request); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the + * {@literal indices} API. * * @param getMappingsRequest must not be {@literal null}. * @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index @@ -1296,12 +1306,13 @@ default Mono getMapping( - org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest) { + org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest) { return getMapping(HttpHeaders.EMPTY, getMappingsRequest); } /** - * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the {@literal indices} API. + * Execute the given {@link org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest} against the + * {@literal indices} API. * * @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}. * @param getMappingsRequest must not be {@literal null}. @@ -1314,7 +1325,7 @@ default Mono getMapping(HttpHeaders headers, - org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest); + org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest getMappingsRequest); /** * Execute the given {@link GetMappingsRequest} against the {@literal indices} API. diff --git a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java index c802c044a..4caf7f13b 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplate.java @@ -250,7 +250,7 @@ public T get(String id, Class clazz) { } @Override - public List multiGet(Query query, Class clazz) { + public List> multiGet(Query query, Class clazz) { return multiGet(query, clazz, getIndexCoordinatesFor(clazz)); } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java index 91412c611..c5ddbd597 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/DocumentOperations.java @@ -120,10 +120,10 @@ public interface DocumentOperations { * * @param query the query defining the ids of the objects to get * @param clazz the type of the object to be returned - * @return list of objects, contains null values for ids that are not found + * @return list of {@link MultiGetItem}s * @since 4.1 */ - List multiGet(Query query, Class clazz); + List> multiGet(Query query, Class clazz); /** * Execute a multiGet against elasticsearch for the given ids. @@ -131,9 +131,9 @@ public interface DocumentOperations { * @param query the query defining the ids of the objects to get * @param clazz the type of the object to be returned * @param index the index(es) from which the objects are read. - * @return list of objects, contains null values for ids that are not found + * @return list of {@link MultiGetItem}s */ - List multiGet(Query query, Class clazz, IndexCoordinates index); + List> multiGet(Query query, Class clazz, IndexCoordinates index); /** * Check if an entity with given {@literal id} exists. diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java index 2b2583f87..18360dfc6 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchRestTemplate.java @@ -168,7 +168,7 @@ public T get(String id, Class clazz, IndexCoordinates index) { } @Override - public List multiGet(Query query, Class clazz, IndexCoordinates index) { + public List> multiGet(Query query, Class clazz, IndexCoordinates index) { Assert.notNull(index, "index must not be null"); Assert.notEmpty(query.getIds(), "No Id defined for Query"); @@ -177,7 +177,10 @@ public List multiGet(Query query, Class clazz, IndexCoordinates index) MultiGetResponse result = execute(client -> client.mget(request, RequestOptions.DEFAULT)); DocumentCallback callback = new ReadDocumentCallback<>(elasticsearchConverter, clazz, index); - return DocumentAdapters.from(result).stream().map(callback::doWith).collect(Collectors.toList()); + return DocumentAdapters.from(result).stream() // + .map(multiGetItem -> MultiGetItem.of( // + multiGetItem.isFailed() ? null : callback.doWith(multiGetItem.getItem()), multiGetItem.getFailure())) // + .collect(Collectors.toList()); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java index 0123a5fac..d0d4852a5 100755 --- a/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplate.java @@ -42,7 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; -import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.document.DocumentAdapters; import org.springframework.data.elasticsearch.core.document.SearchDocumentResponse; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; @@ -190,7 +189,7 @@ public T get(String id, Class clazz, IndexCoordinates index) { } @Override - public List multiGet(Query query, Class clazz, IndexCoordinates index) { + public List> multiGet(Query query, Class clazz, IndexCoordinates index) { Assert.notNull(index, "index must not be null"); Assert.notEmpty(query.getIds(), "No Ids defined for Query"); @@ -198,8 +197,11 @@ public List multiGet(Query query, Class clazz, IndexCoordinates index) MultiGetRequestBuilder builder = requestFactory.multiGetRequestBuilder(client, query, clazz, index); DocumentCallback callback = new ReadDocumentCallback<>(elasticsearchConverter, clazz, index); - List documents = DocumentAdapters.from(builder.execute().actionGet()); - return documents.stream().map(callback::doWith).collect(Collectors.toList()); + + return DocumentAdapters.from(builder.execute().actionGet()).stream() // + .map(multiGetItem -> MultiGetItem.of(multiGetItem.isFailed() ? null : callback.doWith(multiGetItem.getItem()), + multiGetItem.getFailure())) + .collect(Collectors.toList()); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/MultiGetItem.java b/src/main/java/org/springframework/data/elasticsearch/core/MultiGetItem.java new file mode 100644 index 000000000..09bf3c933 --- /dev/null +++ b/src/main/java/org/springframework/data/elasticsearch/core/MultiGetItem.java @@ -0,0 +1,96 @@ +/* + * Copyright 2021 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.elasticsearch.core; + +import org.springframework.lang.Nullable; + +/** + * Response object for items returned from multiget requests, encapsulating the returned data and potential error + * information. + * + * @param the entity type + * @author Peter-Josef Meisch + * @since 4.2 + */ +public class MultiGetItem { + @Nullable private final T item; + @Nullable private final Failure failure; + + private MultiGetItem(@Nullable T item, @Nullable Failure failure) { + this.item = item; + this.failure = failure; + } + + public static MultiGetItem of(@Nullable T item, @Nullable Failure failure) { + return new MultiGetItem<>(item, failure); + } + + public boolean hasItem() { + return item != null; + } + + @Nullable + public T getItem() { + return item; + } + + public boolean isFailed() { + return failure != null; + } + + @Nullable + public Failure getFailure() { + return failure; + } + + public static class Failure { + @Nullable private final String index; + @Nullable private final String type; + @Nullable private final String id; + @Nullable private final Exception exception; + + private Failure(@Nullable String index, @Nullable String type, @Nullable String id, @Nullable Exception exception) { + this.index = index; + this.type = type; + this.id = id; + this.exception = exception; + } + + public static Failure of(String index, String type, String id, Exception exception) { + return new Failure(index, type, id, exception); + } + + @Nullable + public String getIndex() { + return index; + } + + @Nullable + public String getType() { + return type; + } + + @Nullable + public String getId() { + return id; + } + + @Nullable + public Exception getException() { + return exception; + } + } +} diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java index c3917e3e4..566fee06f 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveDocumentOperations.java @@ -147,10 +147,10 @@ default Flux saveAll(Iterable entities, IndexCoordinates index) { * * @param query the query defining the ids of the objects to get * @param clazz the type of the object to be returned, used to determine the index - * @return flux with list of nullable objects + * @return flux with list of {@link MultiGetItem}s that contain the entities * @since 4.1 */ - Flux multiGet(Query query, Class clazz); + Flux> multiGet(Query query, Class clazz); /** * Execute a multiGet against elasticsearch for the given ids. @@ -158,10 +158,10 @@ default Flux saveAll(Iterable entities, IndexCoordinates index) { * @param query the query defining the ids of the objects to get * @param clazz the type of the object to be returned * @param index the index(es) from which the objects are read. - * @return flux with list of nullable objects + * @return flux with list of {@link MultiGetItem}s that contain the entities * @since 4.0 */ - Flux multiGet(Query query, Class clazz, IndexCoordinates index); + Flux> multiGet(Query query, Class clazz, IndexCoordinates index); /** * Bulk update all objects. Will do update. diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java index 7d2cf7b18..925f6c948 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplate.java @@ -71,10 +71,10 @@ import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext; import org.springframework.data.elasticsearch.core.query.BulkOptions; +import org.springframework.data.elasticsearch.core.query.ByQueryResponse; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm; -import org.springframework.data.elasticsearch.core.query.ByQueryResponse; import org.springframework.data.elasticsearch.core.query.UpdateQuery; import org.springframework.data.elasticsearch.core.query.UpdateResponse; import org.springframework.data.elasticsearch.core.routing.DefaultRoutingResolver; @@ -298,12 +298,12 @@ private T updateIndexedObject(T entity, IndexedObjectInformation indexedObje } @Override - public Flux multiGet(Query query, Class clazz) { + public Flux> multiGet(Query query, Class clazz) { return multiGet(query, clazz, getIndexCoordinatesFor(clazz)); } @Override - public Flux multiGet(Query query, Class clazz, IndexCoordinates index) { + public Flux> multiGet(Query query, Class clazz, IndexCoordinates index) { Assert.notNull(index, "Index must not be null"); Assert.notNull(clazz, "Class must not be null"); @@ -314,7 +314,12 @@ public Flux multiGet(Query query, Class clazz, IndexCoordinates index) MultiGetRequest request = requestFactory.multiGetRequest(query, clazz, index); return Flux.from(execute(client -> client.multiGet(request))) // - .concatMap(result -> callback.toEntity(DocumentAdapters.from(result))); + .map(DocumentAdapters::from) // + .flatMap(multiGetItem -> multiGetItem.isFailed() // + ? Mono.just(MultiGetItem.of(null, multiGetItem.getFailure())) // + : callback.toEntity(multiGetItem.getItem()) + .map((T item) -> MultiGetItem.of(item, multiGetItem.getFailure())) // + ); } @Override diff --git a/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java index 0ca86324d..c2328aad2 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/ResponseConverter.java @@ -27,6 +27,8 @@ import java.util.stream.Collectors; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; +import org.elasticsearch.action.get.MultiGetItemResponse; +import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.client.indices.GetIndexResponse; import org.elasticsearch.client.indices.GetIndexTemplatesResponse; import org.elasticsearch.client.indices.IndexTemplateMetadata; @@ -213,67 +215,77 @@ private static List aliasDataFromIndexResponse( // endregion - //region templates - @Nullable - public static TemplateData getTemplateData(GetIndexTemplatesResponse getIndexTemplatesResponse, String templateName) { - for (IndexTemplateMetadata indexTemplateMetadata : getIndexTemplatesResponse.getIndexTemplates()) { - - if (indexTemplateMetadata.name().equals(templateName)) { - - Document settings = Document.create(); - Settings templateSettings = indexTemplateMetadata.settings(); - templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key))); - - Map aliases = new LinkedHashMap<>(); - - ImmutableOpenMap aliasesResponse = indexTemplateMetadata.aliases(); - Iterator keysIt = aliasesResponse.keysIt(); - while (keysIt.hasNext()) { - String key = keysIt.next(); - aliases.put(key, ResponseConverter.toAliasData(aliasesResponse.get(key))); - } - - return TemplateData.builder() - .withIndexPatterns(indexTemplateMetadata.patterns().toArray(new String[0])) // - .withSettings(settings) // - .withMapping(Document.from(indexTemplateMetadata.mappings().getSourceAsMap())) // - .withAliases(aliases) // - .withOrder(indexTemplateMetadata.order()) // - .withVersion(indexTemplateMetadata.version()).build(); - } - } - return null; - } - //endregion - - //region settings - /** - * extract the index settings information for a given index - * - * @param response the Elasticsearch response - * @param indexName the index name - * @return settings as {@link Document} - */ - public static Document fromSettingsResponse(GetSettingsResponse response, String indexName) { - - Document settings = Document.create(); - - if (!response.getIndexToDefaultSettings().isEmpty()) { - Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName); - for (String key : defaultSettings.keySet()) { - settings.put(key, defaultSettings.get(key)); - } - } - - if (!response.getIndexToSettings().isEmpty()) { - Settings customSettings = response.getIndexToSettings().get(indexName); - for (String key : customSettings.keySet()) { - settings.put(key, customSettings.get(key)); - } - } - - return settings; - } - //endregion + // region templates + @Nullable + public static TemplateData getTemplateData(GetIndexTemplatesResponse getIndexTemplatesResponse, String templateName) { + for (IndexTemplateMetadata indexTemplateMetadata : getIndexTemplatesResponse.getIndexTemplates()) { + + if (indexTemplateMetadata.name().equals(templateName)) { + + Document settings = Document.create(); + Settings templateSettings = indexTemplateMetadata.settings(); + templateSettings.keySet().forEach(key -> settings.put(key, templateSettings.get(key))); + + Map aliases = new LinkedHashMap<>(); + + ImmutableOpenMap aliasesResponse = indexTemplateMetadata.aliases(); + Iterator keysIt = aliasesResponse.keysIt(); + while (keysIt.hasNext()) { + String key = keysIt.next(); + aliases.put(key, ResponseConverter.toAliasData(aliasesResponse.get(key))); + } + + return TemplateData.builder().withIndexPatterns(indexTemplateMetadata.patterns().toArray(new String[0])) // + .withSettings(settings) // + .withMapping(Document.from(indexTemplateMetadata.mappings().getSourceAsMap())) // + .withAliases(aliases) // + .withOrder(indexTemplateMetadata.order()) // + .withVersion(indexTemplateMetadata.version()).build(); + } + } + return null; + } + // endregion + + // region settings + /** + * extract the index settings information for a given index + * + * @param response the Elasticsearch response + * @param indexName the index name + * @return settings as {@link Document} + */ + public static Document fromSettingsResponse(GetSettingsResponse response, String indexName) { + + Document settings = Document.create(); + + if (!response.getIndexToDefaultSettings().isEmpty()) { + Settings defaultSettings = response.getIndexToDefaultSettings().get(indexName); + for (String key : defaultSettings.keySet()) { + settings.put(key, defaultSettings.get(key)); + } + } + + if (!response.getIndexToSettings().isEmpty()) { + Settings customSettings = response.getIndexToSettings().get(indexName); + for (String key : customSettings.keySet()) { + settings.put(key, customSettings.get(key)); + } + } + + return settings; + } + // endregion + + // region multiget + + @Nullable + public static MultiGetItem.Failure getFailure(MultiGetItemResponse itemResponse) { + + MultiGetResponse.Failure responseFailure = itemResponse.getFailure(); + return responseFailure != null ? MultiGetItem.Failure.of(responseFailure.getIndex(), responseFailure.getType(), + responseFailure.getId(), responseFailure.getFailure()) : null; + } + // endregion } diff --git a/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java b/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java index e42057fd3..ae4dc09fa 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/document/DocumentAdapters.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetResponse; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.document.DocumentField; @@ -39,6 +40,8 @@ import org.elasticsearch.index.get.GetResult; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; +import org.springframework.data.elasticsearch.core.MultiGetItem; +import org.springframework.data.elasticsearch.core.ResponseConverter; import org.springframework.data.mapping.MappingException; import org.springframework.lang.Nullable; import org.springframework.util.Assert; @@ -126,21 +129,32 @@ public static Document from(GetResult source) { } /** - * Creates a List of {@link Document}s from {@link MultiGetResponse}. + * Creates a List of {@link MultiGetItem}s from {@link MultiGetResponse}. * * @param source the source {@link MultiGetResponse}, not {@literal null}. * @return a list of Documents, contains null values for not found Documents. */ - public static List from(MultiGetResponse source) { + public static List> from(MultiGetResponse source) { Assert.notNull(source, "MultiGetResponse must not be null"); - // noinspection ReturnOfNull return Arrays.stream(source.getResponses()) // - .map(itemResponse -> itemResponse.isFailed() ? null : DocumentAdapters.from(itemResponse.getResponse())) // + .map(DocumentAdapters::from) // .collect(Collectors.toList()); } + /** + * Creates a {@link MultiGetItem} from a {@link MultiGetItemResponse}. + * + * @param itemResponse the response, must not be {@literal null} + * @return the MultiGetItem + */ + public static MultiGetItem from(MultiGetItemResponse itemResponse) { + + MultiGetItem.Failure failure = ResponseConverter.getFailure(itemResponse); + return MultiGetItem.of(itemResponse.isFailed() ? null : DocumentAdapters.from(itemResponse.getResponse()), failure); + } + /** * Create a {@link SearchDocument} from {@link SearchHit}. *

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 80c61a48b..7e8a4c252 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 @@ -34,6 +34,7 @@ import org.springframework.data.elasticsearch.core.AbstractElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.IndexOperations; +import org.springframework.data.elasticsearch.core.MultiGetItem; import org.springframework.data.elasticsearch.core.RefreshPolicy; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHitSupport; @@ -154,13 +155,14 @@ public Iterable findAllById(Iterable ids) { return result; } - List multiGetEntities = execute(operations -> operations.multiGet(idQuery, entityClass, getIndexCoordinates())); + List> multiGetItems = execute( + operations -> operations.multiGet(idQuery, entityClass, getIndexCoordinates())); - if (multiGetEntities != null) { - multiGetEntities.forEach(entity -> { + if (multiGetItems != null) { + multiGetItems.forEach(multiGetItem -> { - if (entity != null) { - result.add(entity); + if (multiGetItem.hasItem()) { + result.add(multiGetItem.getItem()); } }); } 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 f93693bea..c863333e4 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 @@ -22,6 +22,7 @@ import org.reactivestreams.Publisher; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.MultiGetItem; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations; import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate; import org.springframework.data.elasticsearch.core.ReactiveIndexOperations; @@ -161,9 +162,10 @@ public Flux findAllById(Publisher idStream) { .collectList() // .map(ids -> new NativeSearchQueryBuilder().withIds(ids).build()) // .flatMapMany(query -> { - IndexCoordinates index = entityInformation.getIndexCoordinates(); - return operations.multiGet(query, entityInformation.getJavaType(), index); + return operations.multiGet(query, entityInformation.getJavaType(), index) // + .filter(MultiGetItem::hasItem) // + .map(MultiGetItem::getItem); }); } diff --git a/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientIntegrationTests.java index fea6d3395..1bfa6053a 100644 --- a/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientIntegrationTests.java @@ -18,10 +18,6 @@ import static org.assertj.core.api.Assertions.*; import lombok.SneakyThrows; -import org.elasticsearch.client.indices.CreateIndexRequest; -import org.elasticsearch.client.indices.GetIndexRequest; -import org.elasticsearch.client.indices.GetMappingsRequest; -import org.elasticsearch.common.xcontent.XContentType; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -45,8 +41,10 @@ import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.client.indices.CreateIndexRequest; +import org.elasticsearch.client.indices.GetIndexRequest; +import org.elasticsearch.client.indices.GetMappingsRequest; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.reindex.BulkByScrollResponse; import org.elasticsearch.index.reindex.DeleteByQueryRequest; @@ -197,7 +195,7 @@ public void getShouldCompleteForNonExistingDocuments() { .verifyComplete(); } - @Test // DATAES-488 + @Test // DATAES-488, #1678 public void multiGetShouldReturnAllDocumentsFromSameCollection() { String id1 = addSourceDocument().to(INDEX_I); @@ -209,12 +207,18 @@ public void multiGetShouldReturnAllDocumentsFromSameCollection() { client.multiGet(request) // .as(StepVerifier::create) // - .consumeNextWith(it -> assertThat(it.getId()).isEqualTo(id1)) // - .consumeNextWith(it -> assertThat(it.getId()).isEqualTo(id2)) // + .consumeNextWith(it -> { + assertThat(it.getResponse().isExists()).isTrue(); // + assertThat(it.getId()).isEqualTo(id1); // + }) // + .consumeNextWith(it -> { + assertThat(it.getResponse().isExists()).isTrue(); // + assertThat(it.getId()).isEqualTo(id2); // + }) // .verifyComplete(); } - @Test // DATAES-488 + @Test // DATAES-488, #1678 public void multiGetShouldReturnAllExistingDocumentsFromSameCollection() { String id1 = addSourceDocument().to(INDEX_I); @@ -226,12 +230,20 @@ public void multiGetShouldReturnAllExistingDocumentsFromSameCollection() { client.multiGet(request) // .as(StepVerifier::create) // - .consumeNextWith(it -> assertThat(it.getId()).isEqualTo(id1)) // + .consumeNextWith(it -> { + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getResponse().isExists()).isTrue(); // + assertThat(it.getId()).isEqualTo(id1); // + }) // + .consumeNextWith(it -> { + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getResponse().isExists()).isFalse(); // + }) // .verifyComplete(); } - @Test // DATAES-488 - public void multiGetShouldSkipNonExistingDocuments() { + @Test // DATAES-488, #1678 + public void multiGetShouldNotSkipNonExistingDocuments() { String id1 = addSourceDocument().to(INDEX_I); String id2 = addSourceDocument().to(INDEX_I); @@ -242,9 +254,21 @@ public void multiGetShouldSkipNonExistingDocuments() { .add(INDEX_I, id2); // client.multiGet(request) // - .map(GetResult::getId) // .as(StepVerifier::create) // - .expectNext(id1, id2) // + .consumeNextWith(it -> { + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getResponse().isExists()).isTrue(); // + assertThat(it.getId()).isEqualTo(id1); // + }) // + .consumeNextWith(it -> { + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getResponse().isExists()).isFalse(); + }) // + .consumeNextWith(it -> { + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getResponse().isExists()).isTrue(); // + assertThat(it.getId()).isEqualTo(id2); // + }) // .verifyComplete(); } @@ -257,10 +281,12 @@ public void multiGetShouldCompleteIfNothingFound() { client.multiGet(new MultiGetRequest() // .add(INDEX_II, id1).add(INDEX_II, id2)) // .as(StepVerifier::create) // + .consumeNextWith(it -> assertThat(it.isFailed()).isTrue()) // + .consumeNextWith(it -> assertThat(it.isFailed()).isTrue()) // .verifyComplete(); } - @Test // DATAES-488 + @Test // DATAES-488, #1678 public void multiGetShouldReturnAllExistingDocumentsFromDifferentCollection() { String id1 = addSourceDocument().to(INDEX_I); @@ -271,10 +297,16 @@ public void multiGetShouldReturnAllExistingDocumentsFromDifferentCollection() { .add(INDEX_II, id2); client.multiGet(request) // - .map(GetResult::getId) // .as(StepVerifier::create) // - .expectNext(id1, id2) // - .verifyComplete(); + .consumeNextWith(it -> { // + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getId()).isEqualTo(id1); // + }) // + .consumeNextWith(it -> { // + assertThat(it.isFailed()).isFalse(); // + assertThat(it.getId()).isEqualTo(id2); // + }) // + .verifyComplete(); // } @Test // DATAES-488 @@ -587,27 +619,27 @@ public void indexExistsShouldReturnFalseIfNot() { .verifyComplete(); } - @Test // #1658 - public void indexExistsShouldReturnTrueIfExists() { + @Test // #1658 + public void indexExistsShouldReturnTrueIfExists() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - client.indices().existsIndex(new GetIndexRequest(INDEX_I)) // - .as(StepVerifier::create) // - .expectNext(true) // - .verifyComplete(); - } + client.indices().existsIndex(new GetIndexRequest(INDEX_I)) // + .as(StepVerifier::create) // + .expectNext(true) // + .verifyComplete(); + } - @Test // #1658 - public void indexExistsShouldReturnFalseIfNotExists() { + @Test // #1658 + public void indexExistsShouldReturnFalseIfNotExists() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - client.indices().existsIndex(new GetIndexRequest(INDEX_II)) // - .as(StepVerifier::create) // - .expectNext(false) // - .verifyComplete(); - } + client.indices().existsIndex(new GetIndexRequest(INDEX_II)) // + .as(StepVerifier::create) // + .expectNext(false) // + .verifyComplete(); + } @Test // DATAES-569, DATAES-678 public void createIndex() { @@ -633,54 +665,47 @@ public void createExistingIndexErrors() { .verifyError(ElasticsearchStatusException.class); } - @Test // #1658 - public void createIndex_() { + @Test // #1658 + public void createIndex_() { - client.indices().createIndex(new CreateIndexRequest(INDEX_I)) - .as(StepVerifier::create) - .expectNext(true) - .verifyComplete(); - - operations.indexOps(IndexCoordinates.of(INDEX_I)).exists() // - .as(StepVerifier::create) // - .expectNext(true) // - .verifyComplete(); - } + client.indices().createIndex(new CreateIndexRequest(INDEX_I)).as(StepVerifier::create).expectNext(true) + .verifyComplete(); - @Test // #1658 - public void createExistingIndexErrors_() { + operations.indexOps(IndexCoordinates.of(INDEX_I)).exists() // + .as(StepVerifier::create) // + .expectNext(true) // + .verifyComplete(); + } - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + @Test // #1658 + public void createExistingIndexErrors_() { - client.indices().createIndex(new CreateIndexRequest(INDEX_I)) // - .as(StepVerifier::create) // - .verifyError(ElasticsearchStatusException.class); - } + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - @Test // #1658 - public void getIndex() { + client.indices().createIndex(new CreateIndexRequest(INDEX_I)) // + .as(StepVerifier::create) // + .verifyError(ElasticsearchStatusException.class); + } - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + @Test // #1658 + public void getIndex() { - client.indices().getIndex(new GetIndexRequest(INDEX_I)) - .as(StepVerifier::create) - .consumeNextWith(it -> { - assertThat(it.getIndices().length).isOne(); - assertThat(it.getIndices()[0]).isEqualTo(INDEX_I); - }) - .verifyComplete(); - } + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - @Test // #1658 - public void getIndexError() { + client.indices().getIndex(new GetIndexRequest(INDEX_I)).as(StepVerifier::create).consumeNextWith(it -> { + assertThat(it.getIndices().length).isOne(); + assertThat(it.getIndices()[0]).isEqualTo(INDEX_I); + }).verifyComplete(); + } - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + @Test // #1658 + public void getIndexError() { - client.indices().getIndex(new GetIndexRequest(INDEX_II)) - .as(StepVerifier::create) - .verifyError(ElasticsearchStatusException.class); - } + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + client.indices().getIndex(new GetIndexRequest(INDEX_II)).as(StepVerifier::create) + .verifyError(ElasticsearchStatusException.class); + } @Test // DATAES-569, DATAES-678 public void deleteExistingIndex() { @@ -761,81 +786,80 @@ public void refreshNonExistingIndex() { .verifyError(ElasticsearchStatusException.class); } - @Test // #1640 - void putMapping() { + @Test // #1640 + void putMapping() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - Map jsonMap = Collections.singletonMap("properties", - Collections.singletonMap("message", Collections.singletonMap("type", "text"))); + Map jsonMap = Collections.singletonMap("properties", + Collections.singletonMap("message", Collections.singletonMap("type", "text"))); - org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = - new org.elasticsearch.client.indices.PutMappingRequest(INDEX_I).source(jsonMap); + org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = new org.elasticsearch.client.indices.PutMappingRequest( + INDEX_I).source(jsonMap); - client.indices().putMapping(putMappingRequest) // - .as(StepVerifier::create) // - .expectNext(true) // - .verifyComplete(); - } + client.indices().putMapping(putMappingRequest) // + .as(StepVerifier::create) // + .expectNext(true) // + .verifyComplete(); + } - @Test // #1640 - void putMappingError() { + @Test // #1640 + void putMappingError() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - Map jsonMap = Collections.singletonMap("properties", - Collections.singletonMap("message", Collections.singletonMap("type", "text"))); + Map jsonMap = Collections.singletonMap("properties", + Collections.singletonMap("message", Collections.singletonMap("type", "text"))); - org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = - new org.elasticsearch.client.indices.PutMappingRequest(INDEX_II).source(jsonMap); + org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = new org.elasticsearch.client.indices.PutMappingRequest( + INDEX_II).source(jsonMap); - client.indices().putMapping(putMappingRequest) // - .as(StepVerifier::create) // - .verifyError(ElasticsearchStatusException.class); - } + client.indices().putMapping(putMappingRequest) // + .as(StepVerifier::create) // + .verifyError(ElasticsearchStatusException.class); + } - @Test // #1640 - void getMapping() { + @Test // #1640 + void getMapping() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - Map jsonMap = Collections.singletonMap("properties", - Collections.singletonMap("message", Collections.singletonMap("type", "text"))); + Map jsonMap = Collections.singletonMap("properties", + Collections.singletonMap("message", Collections.singletonMap("type", "text"))); - org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = - new org.elasticsearch.client.indices.PutMappingRequest(INDEX_I).source(jsonMap); + org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = new org.elasticsearch.client.indices.PutMappingRequest( + INDEX_I).source(jsonMap); - client.indices().putMapping(putMappingRequest).block(); + client.indices().putMapping(putMappingRequest).block(); - final GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(INDEX_I); + final GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(INDEX_I); - client.indices().getMapping(getMappingsRequest) // - .as(StepVerifier::create) // - .consumeNextWith(it -> { - assertThat(it.mappings().get(INDEX_I).getSourceAsMap()).isEqualTo(jsonMap); - }) - .verifyComplete(); - } + client.indices().getMapping(getMappingsRequest) // + .as(StepVerifier::create) // + .consumeNextWith(it -> { + assertThat(it.mappings().get(INDEX_I).getSourceAsMap()).isEqualTo(jsonMap); + }).verifyComplete(); + } - @Test // #1640 - void getMappingError() { + @Test // #1640 + void getMappingError() { - operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); + operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block(); - Map jsonMap = Collections.singletonMap("properties", - Collections.singletonMap("message", Collections.singletonMap("type", "text"))); + Map jsonMap = Collections.singletonMap("properties", + Collections.singletonMap("message", Collections.singletonMap("type", "text"))); - org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = - new org.elasticsearch.client.indices.PutMappingRequest(INDEX_I).source(jsonMap); + org.elasticsearch.client.indices.PutMappingRequest putMappingRequest = new org.elasticsearch.client.indices.PutMappingRequest( + INDEX_I).source(jsonMap); - client.indices().putMapping(putMappingRequest).block(); + client.indices().putMapping(putMappingRequest).block(); - final GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(INDEX_II); + final GetMappingsRequest getMappingsRequest = new GetMappingsRequest().indices(INDEX_II); - client.indices().getMapping(getMappingsRequest) // - .as(StepVerifier::create) // - .verifyError(ElasticsearchStatusException.class); - } + client.indices().getMapping(getMappingsRequest) // + .as(StepVerifier::create) // + .verifyError(ElasticsearchStatusException.class); + } @Test // DATAES-569 public void updateMapping() { diff --git a/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientUnitTests.java b/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientUnitTests.java index b4fab9390..ac30ab48f 100644 --- a/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientUnitTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/client/reactive/ReactiveElasticsearchClientUnitTests.java @@ -242,30 +242,30 @@ public void multiGetShouldHitMGetEndpoint() { assertThat(uri.getRawPath()).isEqualTo("/_mget"); } - @Test // DATAES-488 + @Test // DATAES-488, #1678 public void multiGetShouldReturnExistingDocuments() { hostProvider.when(HOST) // .receiveJsonFromFile("multi-get-ok-2-hits"); - client.multiGet(new MultiGetRequest().add("twitter", "_doc", "1").add("twitter", "_doc", "2")) // + client.multiGet(new MultiGetRequest().add("twitter", "1").add("twitter", "2")) // .as(StepVerifier::create) // .consumeNextWith(result -> { - assertThat(result.isExists()).isTrue(); + assertThat(result.isFailed()).isFalse(); assertThat(result.getIndex()).isEqualTo("twitter"); assertThat(result.getId()).isEqualTo("1"); - assertThat(result.getSource()) // + assertThat(result.getResponse().getSource()) // .containsEntry("user", "kimchy") // .containsEntry("message", "Trying out Elasticsearch, so far so good?") // .containsKey("post_date"); }) // .consumeNextWith(result -> { - assertThat(result.isExists()).isTrue(); + assertThat(result.isFailed()).isFalse(); assertThat(result.getIndex()).isEqualTo("twitter"); assertThat(result.getId()).isEqualTo("2"); - assertThat(result.getSource()) // + assertThat(result.getResponse().getSource()) // .containsEntry("user", "kimchy") // .containsEntry("message", "Another tweet, will it be indexed?") // .containsKey("post_date"); @@ -273,33 +273,44 @@ public void multiGetShouldReturnExistingDocuments() { .verifyComplete(); } - @Test // DATAES-488 + @Test // DATAES-488, #1678 public void multiGetShouldWorkForNonExistingDocuments() { hostProvider.when(HOST) // .receiveJsonFromFile("multi-get-ok-2-hits-1-unavailable"); - client.multiGet(new MultiGetRequest().add("twitter", "_doc", "1").add("twitter", "_doc", "2")) // + client.multiGet(new MultiGetRequest() // + .add("twitter", "1") // + .add("twitter", "2") // + .add("twitter", "3") // + ) // .as(StepVerifier::create) // .consumeNextWith(result -> { - assertThat(result.isExists()).isTrue(); + assertThat(result.isFailed()).isFalse(); assertThat(result.getIndex()).isEqualTo("twitter"); assertThat(result.getId()).isEqualTo("1"); - assertThat(result.getSource()) // + assertThat(result.getResponse().isExists()).isTrue(); + assertThat(result.getResponse().getSource()) // .containsEntry("user", "kimchy") // .containsEntry("message", "Trying out Elasticsearch, so far so good?") // .containsKey("post_date"); }) // .consumeNextWith(result -> { - assertThat(result.isExists()).isTrue(); - assertThat(result.getIndex()).isEqualTo("twitter"); - assertThat(result.getId()).isEqualTo("3"); - assertThat(result.getSource()) // - .containsEntry("user", "elastic") // - .containsEntry("message", "Building the site, should be kewl") // - .containsKey("post_date"); + assertThat(result.isFailed()).isFalse(); + assertThat(result.getResponse().isExists()).isFalse(); + }) // + .consumeNextWith(result -> { + + assertThat(result.isFailed()).isFalse(); + assertThat(result.getIndex()).isEqualTo("twitter"); + assertThat(result.getId()).isEqualTo("3"); + assertThat(result.getResponse().isExists()).isTrue(); + assertThat(result.getResponse().getSource()) // + .containsEntry("user", "elastic") // + .containsEntry("message", "Building the site, should be kewl") // + .containsKey("post_date"); }) // .verifyComplete(); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java index 9815b30e3..a4ea0314b 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/AbstractElasticsearchTemplateCallbackTests.java @@ -234,17 +234,17 @@ void getWithCoordinatesShouldInvokeAfterConvertCallback() { assertThat(result.firstname).isEqualTo("after-convert"); } - @Test // DATAES-772 + @Test // DATAES-772, #1678 void multiGetShouldInvokeAfterConvertCallback() { template.setEntityCallbacks(EntityCallbacks.create(afterConvertCallback)); - List results = template.multiGet(queryForTwo(), Person.class, index); + List> results = template.multiGet(queryForTwo(), Person.class, index); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).firstname).isEqualTo("after-convert"); - assertThat(results.get(1).firstname).isEqualTo("after-convert"); + assertThat(results.get(0).getItem().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getItem().firstname).isEqualTo("after-convert"); } private Query queryForTwo() { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java index 59b8c1f25..a83142205 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -237,7 +237,7 @@ public void shouldReturnObjectForGivenId() { assertThat(sampleEntity1).isEqualTo(sampleEntity); } - @Test // DATAES-52 + @Test // DATAES-52, #1678 public void shouldReturnObjectsForGivenIdsUsingMultiGet() { // given @@ -258,15 +258,15 @@ public void shouldReturnObjectsForGivenIdsUsingMultiGet() { // when NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)).build(); - List sampleEntities = operations.multiGet(query, SampleEntity.class, index); + List> sampleEntities = operations.multiGet(query, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(2); - assertThat(sampleEntities.get(0)).isEqualTo(sampleEntity1); - assertThat(sampleEntities.get(1)).isEqualTo(sampleEntity2); + assertThat(sampleEntities.get(0).getItem()).isEqualTo(sampleEntity1); + assertThat(sampleEntities.get(1).getItem()).isEqualTo(sampleEntity2); } - @Test // DATAES-791 + @Test // DATAES-791, #1678 public void shouldReturnNullObjectForNotExistingIdUsingMultiGet() { // given @@ -290,16 +290,30 @@ public void shouldReturnNullObjectForNotExistingIdUsingMultiGet() { assertThat(idsToSearch).hasSize(3); NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(idsToSearch).build(); - List sampleEntities = operations.multiGet(query, SampleEntity.class, index); + List> sampleEntities = operations.multiGet(query, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(3); - assertThat(sampleEntities.get(0)).isEqualTo(sampleEntity1); - assertThat(sampleEntities.get(1)).isNull(); - assertThat(sampleEntities.get(2)).isEqualTo(sampleEntity2); + assertThat(sampleEntities.get(0).getItem()).isEqualTo(sampleEntity1); + assertThat(sampleEntities.get(1).getItem()).isNull(); + assertThat(sampleEntities.get(2).getItem()).isEqualTo(sampleEntity2); } - @Test // DATAES-52 + @Test // #1678 + @DisplayName("should return failure in multiget result") + void shouldReturnFailureInMultigetResult() { + + NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList("42")).build(); + List> sampleEntities = operations.multiGet(query, SampleEntity.class, + IndexCoordinates.of("not-existing-index")); + + // then + assertThat(sampleEntities).hasSize(1); + assertThat(sampleEntities.get(0).isFailed()).isTrue(); + assertThat(sampleEntities.get(0).getFailure()).isNotNull(); + } + + @Test // DATAES-52, #1678 public void shouldReturnObjectsForGivenIdsUsingMultiGetWithFields() { // given @@ -321,7 +335,7 @@ public void shouldReturnObjectsForGivenIdsUsingMultiGetWithFields() { // when NativeSearchQuery query = new NativeSearchQueryBuilder().withIds(Arrays.asList(documentId, documentId2)) .withFields("message", "type").build(); - List sampleEntities = operations.multiGet(query, SampleEntity.class, index); + List> sampleEntities = operations.multiGet(query, SampleEntity.class, index); // then assertThat(sampleEntities).hasSize(2); @@ -3263,9 +3277,9 @@ void multigetShouldReturnSeqNoPrimaryTerm() { OptimisticEntity saved = operations.save(original); operations.indexOps(OptimisticEntity.class).refresh(); - List retrievedList = operations.multiGet(queryForOne(saved.getId()), OptimisticEntity.class, - operations.getIndexCoordinatesFor(OptimisticEntity.class)); - OptimisticEntity retrieved = retrievedList.get(0); + List> retrievedList = operations.multiGet(queryForOne(saved.getId()), + OptimisticEntity.class, operations.getIndexCoordinatesFor(OptimisticEntity.class)); + OptimisticEntity retrieved = retrievedList.get(0).getItem(); assertThatSeqNoPrimaryTermIsFilled(retrieved); } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java index d523fe50c..bfff6f2f6 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateCallbackTests.java @@ -21,6 +21,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.action.get.MultiGetItemResponse; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -85,6 +87,8 @@ public class ReactiveElasticsearchTemplateCallbackTests { @Mock private BulkItemResponse bulkItemResponse; @Mock private DocWriteResponse docWriteResponse; @Mock private GetResult getResult; + @Mock private GetResponse getResponse; + @Mock private MultiGetItemResponse multiGetItemResponse; @Mock private org.elasticsearch.search.SearchHit searchHit; @Mock private org.elasticsearch.action.search.SearchResponse searchResponse; @@ -109,8 +113,6 @@ public void setUp() { doReturn(docWriteResponse).when(bulkItemResponse).getResponse(); doReturn("response-id").when(docWriteResponse).getId(); - when(client.multiGet(any(MultiGetRequest.class))).thenReturn(Flux.just(getResult, getResult)); - doReturn(true).when(getResult).isExists(); doReturn(false).when(getResult).isSourceEmpty(); doReturn(new HashMap() { @@ -120,6 +122,16 @@ public void setUp() { } }).when(getResult).getSource(); + doReturn(true).when(getResponse).isExists(); + doReturn(new HashMap() { + { + put("id", "init"); + put("firstname", "luke"); + } + }).when(getResponse).getSourceAsMap(); + doReturn(getResponse).when(multiGetItemResponse).getResponse(); + when(client.multiGet(any(MultiGetRequest.class))).thenReturn(Flux.just(multiGetItemResponse, multiGetItemResponse)); + doReturn(Mono.just(getResult)).when(client).get(any(GetRequest.class)); when(client.search(any(SearchRequest.class))).thenReturn(Flux.just(searchHit, searchHit)); @@ -224,18 +236,18 @@ void saveFromMonoAllShouldInvokeAfterSaveCallbacks() { assertThat(saved.get(1).firstname).isEqualTo("after-save"); } - @Test // DATAES-772 + @Test // DATAES-772, #1678 void multiGetShouldInvokeAfterConvertCallbacks() { template.setEntityCallbacks(ReactiveEntityCallbacks.create(afterConvertCallback)); - List results = template.multiGet(pagedQueryForTwo(), Person.class, index).timeout(Duration.ofSeconds(1)) + List> results = template.multiGet(pagedQueryForTwo(), Person.class, index).timeout(Duration.ofSeconds(1)) .toStream().collect(Collectors.toList()); verify(afterConvertCallback, times(2)).onAfterConvert(eq(new Person("init", "luke")), eq(lukeDocument()), eq(index)); - assertThat(results.get(0).firstname).isEqualTo("after-convert"); - assertThat(results.get(1).firstname).isEqualTo("after-convert"); + assertThat(results.get(0).getItem().firstname).isEqualTo("after-convert"); + assertThat(results.get(1).getItem().firstname).isEqualTo("after-convert"); } @Test // DATAES-772 diff --git a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java index 793f40d38..69b09aac9 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ReactiveElasticsearchTemplateIntegrationTests.java @@ -772,7 +772,7 @@ void shouldReturnSortFields() { .verifyComplete(); } - @Test // DATAES-623 + @Test // DATAES-623, #1678 public void shouldReturnObjectsForGivenIdsUsingMultiGet() { SampleEntity entity1 = randomEntity("test message 1"); entity1.rate = 1; @@ -786,7 +786,7 @@ public void shouldReturnObjectsForGivenIdsUsingMultiGet() { .build(); template.multiGet(query, SampleEntity.class, IndexCoordinates.of(DEFAULT_INDEX)) // - .as(StepVerifier::create) // + .map(MultiGetItem::getItem).as(StepVerifier::create) // .expectNext(entity1, entity2) // .verifyComplete(); } @@ -811,7 +811,7 @@ public void shouldReturnObjectsForGivenIdsUsingMultiGetWithFields() { .verifyComplete(); } - @Test // DATAES-623 + @Test // DATAES-623. #1678 public void shouldDoBulkUpdate() { SampleEntity entity1 = randomEntity("test message 1"); entity1.rate = 1; @@ -841,6 +841,7 @@ public void shouldDoBulkUpdate() { .withIds(Arrays.asList(entity1.getId(), entity2.getId())) // .build(); template.multiGet(getQuery, SampleEntity.class, IndexCoordinates.of(DEFAULT_INDEX)) // + .map(MultiGetItem::getItem) // .as(StepVerifier::create) // .expectNextMatches(entity -> entity.getMessage().equals("updated 1")) // .expectNextMatches(entity -> entity.getMessage().equals("updated 2")) // @@ -891,7 +892,7 @@ private void assertThatSeqNoPrimaryTermIsFilled(OptimisticEntity retrieved) { assertThat(retrieved.seqNoPrimaryTerm.getPrimaryTerm()).isPositive(); } - @Test // DATAES-799 + @Test // DATAES-799, #1678 void multiGetShouldReturnSeqNoPrimaryTerm() { OptimisticEntity original = new OptimisticEntity(); original.setMessage("It's fine"); @@ -899,8 +900,10 @@ void multiGetShouldReturnSeqNoPrimaryTerm() { template .multiGet(multiGetQueryForOne(saved.getId()), OptimisticEntity.class, - template.getIndexCoordinatesFor(OptimisticEntity.class)) - .as(StepVerifier::create).assertNext(this::assertThatSeqNoPrimaryTermIsFilled).verifyComplete(); + template.getIndexCoordinatesFor(OptimisticEntity.class)) // + .map(MultiGetItem::getItem) // + .as(StepVerifier::create) // + .assertNext(this::assertThatSeqNoPrimaryTermIsFilled).verifyComplete(); } private Query multiGetQueryForOne(String id) { diff --git a/src/test/java/org/springframework/data/elasticsearch/core/SourceFilterIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/SourceFilterIntegrationTests.java index 50d62d79d..abcc79998 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/SourceFilterIntegrationTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/SourceFilterIntegrationTests.java @@ -81,17 +81,17 @@ void shouldOnlyReturnRequestedFieldsOnSearch() { assertThat(entity.getField3()).isNull(); } - @Test // #1659 + @Test // #1659, #1678 @DisplayName("should only return requested fields on multiget") void shouldOnlyReturnRequestedFieldsOnGMultiGet() { Query query = new NativeSearchQueryBuilder().withIds(Collections.singleton("42")).build(); query.addFields("field2"); - List entities = operations.multiGet(query, Entity.class); + List> entities = operations.multiGet(query, Entity.class); assertThat(entities).hasSize(1); - Entity entity = entities.get(0); + Entity entity = entities.get(0).getItem(); assertThat(entity.getField1()).isNull(); assertThat(entity.getField2()).isEqualTo("two"); assertThat(entity.getField3()).isNull(); @@ -123,7 +123,7 @@ public String[] getExcludes() { assertThat(entity.getField3()).isNotNull(); } - @Test // #1659 + @Test // #1659, #1678 @DisplayName("should not return excluded fields from SourceFilter on multiget") void shouldNotReturnExcludedFieldsFromSourceFilterOnMultiGet() { @@ -140,10 +140,10 @@ public String[] getExcludes() { } }); - List entities = operations.multiGet(query, Entity.class); + List> entities = operations.multiGet(query, Entity.class); assertThat(entities).hasSize(1); - Entity entity = entities.get(0); + Entity entity = entities.get(0).getItem(); assertThat(entity.getField1()).isNotNull(); assertThat(entity.getField2()).isNull(); assertThat(entity.getField3()).isNotNull(); @@ -175,7 +175,7 @@ public String[] getExcludes() { assertThat(entity.getField3()).isNull(); } - @Test // #1659 + @Test // #1659, #1678 @DisplayName("should only return included fields from SourceFilter on multiget") void shouldOnlyReturnIncludedFieldsFromSourceFilterOnMultiGet() { @@ -192,10 +192,10 @@ public String[] getExcludes() { } }); - List entities = operations.multiGet(query, Entity.class); + List> entities = operations.multiGet(query, Entity.class); assertThat(entities).hasSize(1); - Entity entity = entities.get(0); + Entity entity = entities.get(0).getItem(); assertThat(entity.getField1()).isNull(); assertThat(entity.getField2()).isNotNull(); assertThat(entity.getField3()).isNull();