Overload multiSearch method to support list of IndexCoordinates.

Original Pull Request #2436
Closes #2434
This commit is contained in:
Hamid Rahimi 2023-01-26 19:03:35 +01:00 committed by GitHub
parent b3f9bdb80f
commit b0c2ce3084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 1 deletions

View File

@ -69,6 +69,7 @@ import org.springframework.util.Assert;
* Elasticsearch client.
*
* @author Peter-Josef Meisch
* @author Hamid Rahimi
* @since 4.4
*/
public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
@ -465,6 +466,29 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
return doMultiSearch(multiSearchQueryParameters);
}
@Override
public List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes,
List<IndexCoordinates> indexes) {
Assert.notNull(queries, "queries must not be null");
Assert.notNull(classes, "classes must not be null");
Assert.notNull(indexes, "indexes must not be null");
Assert.isTrue(queries.size() == classes.size() && queries.size() == indexes.size(),
"queries, classes and indexes must have the same size");
List<MultiSearchQueryParameter> multiSearchQueryParameters = new ArrayList<>(queries.size());
Iterator<Class<?>> it = classes.iterator();
Iterator<IndexCoordinates> indexesIt = indexes.iterator();
for (Query query : queries) {
Class<?> clazz = it.next();
IndexCoordinates index = indexesIt.next();
multiSearchQueryParameters.add(new MultiSearchQueryParameter(query, clazz, index));
}
return doMultiSearch(multiSearchQueryParameters);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private List<SearchHits<?>> doMultiSearch(List<MultiSearchQueryParameter> multiSearchQueryParameters) {

View File

@ -112,6 +112,7 @@ import org.springframework.util.Assert;
* @author Massimiliano Poggi
* @author Farid Faoudi
* @author Sijia Liu
* @author Hamid Rahimi
* @since 4.4
* @deprecated since 5.0
*/
@ -558,6 +559,42 @@ public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
return res;
}
@Override
public List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes,
List<IndexCoordinates> indexes) {
Assert.notNull(queries, "queries must not be null");
Assert.notNull(classes, "classes must not be null");
Assert.notNull(indexes, "indexes must not be null");
Assert.isTrue(queries.size() == classes.size() && queries.size() == indexes.size(),
"queries, classes and indexes must have the same size");
MultiSearchRequest request = new MultiSearchRequest();
Iterator<Class<?>> it = classes.iterator();
Iterator<IndexCoordinates> indexesIt = indexes.iterator();
for (Query query : queries) {
request.add(requestFactory.searchRequest(query, it.next(), indexesIt.next()));
}
MultiSearchResponse.Item[] items = getMultiSearchResult(request);
List<SearchHits<?>> res = new ArrayList<>(queries.size());
Iterator<Class<?>> it1 = classes.iterator();
Iterator<IndexCoordinates> indexesIt1 = indexes.iterator();
for (int i = 0; i < queries.size(); i++) {
Class entityClass = it1.next();
IndexCoordinates index = indexesIt1.next();
ReadDocumentCallback<?> documentCallback = new ReadDocumentCallback<>(elasticsearchConverter, entityClass, index);
SearchDocumentResponseCallback<SearchHits<?>> callback = new ReadSearchDocumentResponseCallback<>(entityClass,
index);
SearchResponse response = items[i].getResponse();
res.add(callback.doWith(SearchDocumentResponseBuilder.from(response, getEntityCreator(documentCallback))));
}
return res;
}
protected MultiSearchResponse.Item[] getMultiSearchResult(MultiSearchRequest request) {
MultiSearchResponse response = execute(client -> client.msearch(request, RequestOptions.DEFAULT));
MultiSearchResponse.Item[] items = response.getResponses();

View File

@ -30,6 +30,7 @@ import org.springframework.lang.Nullable;
*
* @author Peter-Josef Meisch
* @author Sascha Woo
* @author Hamid Rahimi
* @since 4.0
*/
public interface SearchOperations {
@ -127,11 +128,21 @@ public interface SearchOperations {
*
* @param queries the queries to execute
* @param classes the entity classes used for property mapping
* @param index the index to run the query against
* @param index the index to run the queries against
* @return list of SearchHits
*/
List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes, IndexCoordinates index);
/**
* Execute the multi search query against elasticsearch and return result as {@link List} of {@link SearchHits}.
*
* @param queries the queries to execute
* @param classes the entity classes used for property mapping
* @param indexes the indexes to run the queries against
* @return list of SearchHits
*/
List<SearchHits<?>> multiSearch(List<? extends Query> queries, List<Class<?>> classes, List<IndexCoordinates> indexes);
/**
* Execute the criteria query against elasticsearch and return result as {@link SearchHits}
*

View File

@ -108,6 +108,7 @@ import org.springframework.lang.Nullable;
* @author Sijia Liu
* @author Haibo Liu
* @author scoobyzhang
* @author Hamid Rahimi
*/
@SpringIntegrationTest
public abstract class ElasticsearchIntegrationTests {
@ -1764,6 +1765,40 @@ public abstract class ElasticsearchIntegrationTests {
assertThat(searchHit1.getContent().getClass()).isEqualTo(Book.class);
}
@Test // #2434
public void shouldReturnDifferentEntityForMultiSearchWithMultipleIndexCoordinates() {
IndexOperations bookIndexOperations = operations.indexOps(Book.class);
bookIndexOperations.delete();
bookIndexOperations.createWithMapping();
bookIndexOperations.refresh();
IndexCoordinates bookIndex = IndexCoordinates.of("i-need-my-own-index");
operations.index(buildIndex(SampleEntity.builder().id("1").message("ab").build()),
IndexCoordinates.of(indexNameProvider.indexName()));
operations.index(buildIndex(Book.builder().id("2").description("bc").build()), bookIndex);
bookIndexOperations.refresh();
List<Query> queries = new ArrayList<>();
queries.add(getTermQuery("message", "ab"));
queries.add(getTermQuery("description", "bc"));
List<SearchHits<?>> searchHitsList = operations.multiSearch(queries,
Lists.newArrayList(SampleEntity.class, Book.class),
List.of(IndexCoordinates.of(indexNameProvider.indexName()),
IndexCoordinates.of(bookIndex.getIndexName())));
bookIndexOperations.delete();
SearchHits<?> searchHits0 = searchHitsList.get(0);
assertThat(searchHits0.getTotalHits()).isEqualTo(1L);
SearchHit<SampleEntity> searchHit0 = (SearchHit<SampleEntity>) searchHits0.getSearchHit(0);
assertThat(searchHit0.getContent().getClass()).isEqualTo(SampleEntity.class);
SearchHits<?> searchHits1 = searchHitsList.get(1);
assertThat(searchHits1.getTotalHits()).isEqualTo(1L);
SearchHit<Book> searchHit1 = (SearchHit<Book>) searchHits1.getSearchHit(0);
assertThat(searchHit1.getContent().getClass()).isEqualTo(Book.class);
}
@Test
public void shouldIndexDocumentForSpecifiedSource() {