Skip to content

Commit 2aba7a5

Browse files
committed
Fix IndexOutOfBoundsException when try to map inner hits with no results returned.
Original Pull Request #1998 Closes #1997 (cherry picked from commit 49324a3)
1 parent 15ca49a commit 2aba7a5

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

Diff for: src/main/java/org/springframework/data/elasticsearch/core/SearchHitMapping.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
import java.util.stream.Collectors;
2424

2525
import org.elasticsearch.search.aggregations.Aggregations;
26-
import org.slf4j.Logger;
27-
import org.slf4j.LoggerFactory;
26+
import org.springframework.data.elasticsearch.UncategorizedElasticsearchException;
2827
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
2928
import org.springframework.data.elasticsearch.core.document.Document;
3029
import org.springframework.data.elasticsearch.core.document.NestedMetaData;
@@ -44,12 +43,11 @@
4443
* @author Mark Paluch
4544
* @author Roman Puchkovskiy
4645
* @author Matt Gilene
46+
* @author Sascha Woo
4747
* @since 4.0
4848
*/
4949
class SearchHitMapping<T> {
5050

51-
private static final Logger LOGGER = LoggerFactory.getLogger(SearchHitMapping.class);
52-
5351
private final Class<T> type;
5452
private final ElasticsearchConverter converter;
5553
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
@@ -173,7 +171,7 @@ private Map<String, SearchHits<?>> mapInnerHits(SearchDocument searchDocument) {
173171
*/
174172
private SearchHits<?> mapInnerDocuments(SearchHits<SearchDocument> searchHits, Class<T> type) {
175173

176-
if (searchHits.getTotalHits() == 0) {
174+
if (searchHits.isEmpty()) {
177175
return searchHits;
178176
}
179177

@@ -217,7 +215,7 @@ private SearchHits<?> mapInnerDocuments(SearchHits<SearchDocument> searchHits, C
217215
searchHits.getAggregations());
218216
}
219217
} catch (Exception e) {
220-
LOGGER.warn("Could not map inner_hits", e);
218+
throw new UncategorizedElasticsearchException("Unable to convert inner hits.", e);
221219
}
222220

223221
return searchHits;

Diff for: src/test/java/org/springframework/data/elasticsearch/core/ElasticsearchTemplateTests.java

+43
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@
5050
import org.elasticsearch.common.lucene.search.function.CombineFunction;
5151
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
5252
import org.elasticsearch.index.VersionType;
53+
import org.elasticsearch.index.query.InnerHitBuilder;
5354
import org.elasticsearch.index.query.QueryBuilders;
5455
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
5556
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder.FilterFunctionBuilder;
5657
import org.elasticsearch.index.query.functionscore.GaussDecayFunctionBuilder;
58+
import org.elasticsearch.join.query.HasChildQueryBuilder;
59+
import org.elasticsearch.join.query.JoinQueryBuilders;
5760
import org.elasticsearch.join.query.ParentIdQueryBuilder;
5861
import org.elasticsearch.script.Script;
5962
import org.elasticsearch.script.ScriptType;
@@ -3029,6 +3032,46 @@ public void shouldAddAliasWithGivenRoutingValue() {
30293032
indexOperations.removeAlias(aliasQuery);
30303033
}
30313034

3035+
@Test // #1997
3036+
@DisplayName("should return document with inner hits size zero")
3037+
void shouldReturnDocumentWithInnerHitsSizeZero() {
3038+
3039+
// given
3040+
SampleJoinEntity sampleQuestionEntity1 = new SampleJoinEntity();
3041+
sampleQuestionEntity1.setUuid("q1");
3042+
sampleQuestionEntity1.setText("This is a question");
3043+
sampleQuestionEntity1.setMyJoinField(new JoinField<>("question"));
3044+
3045+
SampleJoinEntity sampleAnswerEntity1 = new SampleJoinEntity();
3046+
sampleAnswerEntity1.setUuid("a1");
3047+
sampleAnswerEntity1.setText("This is an answer");
3048+
sampleAnswerEntity1.setMyJoinField(new JoinField<>("answer", sampleQuestionEntity1.getUuid()));
3049+
3050+
SampleJoinEntity sampleAnswerEntity2 = new SampleJoinEntity();
3051+
sampleAnswerEntity1.setUuid("a2");
3052+
sampleAnswerEntity1.setText("This is an answer");
3053+
sampleAnswerEntity1.setMyJoinField(new JoinField<>("answer", sampleQuestionEntity1.getUuid()));
3054+
3055+
IndexOperations indexOps = operations.indexOps(SampleJoinEntity.class);
3056+
operations.save(Arrays.asList(sampleQuestionEntity1, sampleAnswerEntity1, sampleAnswerEntity2));
3057+
indexOps.refresh();
3058+
3059+
// when
3060+
Query query = new NativeSearchQueryBuilder().withQuery(
3061+
JoinQueryBuilders.hasChildQuery("answer", matchAllQuery(), org.apache.lucene.search.join.ScoreMode.Avg)
3062+
.innerHit(new InnerHitBuilder("innerHits").setSize(0)))
3063+
.build();
3064+
3065+
SearchHits<SampleJoinEntity> searchHits = operations.search(query, SampleJoinEntity.class);
3066+
3067+
// then
3068+
assertThat(searchHits).isNotNull();
3069+
assertThat(searchHits.getTotalHits()).isEqualTo(1);
3070+
assertThat(searchHits.getSearchHits()).hasSize(1);
3071+
assertThat(searchHits.getSearchHit(0).getInnerHits().size()).isEqualTo(1);
3072+
assertThat(searchHits.getSearchHit(0).getInnerHits("innerHits").getTotalHits()).isEqualTo(1);
3073+
}
3074+
30323075
@Test // DATAES-541
30333076
public void shouldRemoveAlias() {
30343077

0 commit comments

Comments
 (0)