Filter out empty top docs results before merging (#126385)

`Lucene.EMPTY_TOP_DOCS` to identify empty to docs results. These were previously
null results, but did not need to be send over transport as incremental reduction
was performed only on the data node.

Now it can happen that the coord node received a merge result with empty top docs,
which has nothing interesting for merging, but that can lead to an exception because
the type of the empty array does not match the type of other shards results, for
instance if the query was sorted by field. To resolve this, we filter out empty
top docs results before merging.

Closes #126118
This commit is contained in:
Luca Cavanna 2025-04-10 10:03:10 +02:00 committed by GitHub
parent 62636f958b
commit 0c95d1a48e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 8 additions and 2 deletions

View file

@ -0,0 +1,6 @@
pr: 126385
summary: Filter out empty top docs results before merging
area: Search
type: bug
issues:
- 126118

View file

@ -150,11 +150,11 @@ public final class SearchPhaseController {
return topDocs;
} else if (topDocs instanceof TopFieldGroups firstTopDocs) {
final Sort sort = new Sort(firstTopDocs.fields);
final TopFieldGroups[] shardTopDocs = results.toArray(new TopFieldGroups[0]);
final TopFieldGroups[] shardTopDocs = results.stream().filter(td -> td != Lucene.EMPTY_TOP_DOCS).toArray(TopFieldGroups[]::new);
mergedTopDocs = TopFieldGroups.merge(sort, from, topN, shardTopDocs, false);
} else if (topDocs instanceof TopFieldDocs firstTopDocs) {
final Sort sort = checkSameSortTypes(results, firstTopDocs.fields);
final TopFieldDocs[] shardTopDocs = results.toArray(new TopFieldDocs[0]);
final TopFieldDocs[] shardTopDocs = results.stream().filter((td -> td != Lucene.EMPTY_TOP_DOCS)).toArray(TopFieldDocs[]::new);
mergedTopDocs = TopDocs.merge(sort, from, topN, shardTopDocs);
} else {
final TopDocs[] shardTopDocs = results.toArray(new TopDocs[numShards]);