From 49324a369af627e390f981ed6b793f0f503526c7 Mon Sep 17 00:00:00 2001 From: Sascha Woo Date: Tue, 23 Nov 2021 20:08:50 +0100 Subject: [PATCH] Fix IndexOutOfBoundsException when try to map inner hits with no results returned. Original Pull Request #1998 Closes #1997 Co-authored-by: Peter-Josef Meisch --- .../elasticsearch/core/SearchHitMapping.java | 10 +++---- .../core/ElasticsearchTemplateTests.java | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/SearchHitMapping.java b/src/main/java/org/springframework/data/elasticsearch/core/SearchHitMapping.java index a9ff77a20..d746afedd 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/SearchHitMapping.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/SearchHitMapping.java @@ -22,8 +22,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.springframework.data.elasticsearch.UncategorizedElasticsearchException; import org.springframework.data.elasticsearch.backend.elasticsearch7.document.SearchDocumentResponse; import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter; import org.springframework.data.elasticsearch.core.document.Document; @@ -45,12 +44,11 @@ import org.springframework.util.Assert; * @author Mark Paluch * @author Roman Puchkovskiy * @author Matt Gilene + * @author Sascha Woo * @since 4.0 */ public class SearchHitMapping { - private static final Log LOGGER = LogFactory.getLog(SearchHitMapping.class); - private final Class type; private final ElasticsearchConverter converter; private final MappingContext, ElasticsearchPersistentProperty> mappingContext; @@ -194,7 +192,7 @@ public class SearchHitMapping { */ private SearchHits mapInnerDocuments(SearchHits searchHits, Class type) { - if (searchHits.getTotalHits() == 0) { + if (searchHits.isEmpty()) { return searchHits; } @@ -239,7 +237,7 @@ public class SearchHitMapping { searchHits.getSuggest()); } } catch (Exception e) { - LOGGER.warn("Could not map inner_hits", e); + throw new UncategorizedElasticsearchException("Unable to convert inner hits.", e); } return searchHits; 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 b4e278f84..fd045a375 100755 --- a/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java @@ -2787,6 +2787,33 @@ public abstract class ElasticsearchTemplateTests { assertThat(searchHits.getSearchHit(1).getInnerHits("innerHits").getTotalHits()).isEqualTo(1); } + @Test // #1997 + @DisplayName("should return document with inner hits size zero") + void shouldReturnDocumentWithInnerHitsSizeZero() { + + // given + SampleEntity sampleEntity = SampleEntity.builder().id(nextIdAsString()).message("message 1").rate(1) + .version(System.currentTimeMillis()).build(); + + List indexQueries = getIndexQueries(Arrays.asList(sampleEntity)); + + operations.bulkIndex(indexQueries, IndexCoordinates.of(indexNameProvider.indexName())); + + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery()) + .withCollapseBuilder(new CollapseBuilder("rate").setInnerHits(new InnerHitBuilder("innerHits").setSize(0))) + .build(); + + // when + SearchHits searchHits = operations.search(searchQuery, SampleEntity.class, + IndexCoordinates.of(indexNameProvider.indexName())); + + // then + assertThat(searchHits).isNotNull(); + assertThat(searchHits.getTotalHits()).isEqualTo(1); + assertThat(searchHits.getSearchHits()).hasSize(1); + assertThat(searchHits.getSearchHit(0).getContent().getMessage()).isEqualTo("message 1"); + } + private IndexQuery getIndexQuery(SampleEntity sampleEntity) { return new IndexQueryBuilder().withId(sampleEntity.getId()).withObject(sampleEntity) .withVersion(sampleEntity.getVersion()).build();