From e279e602c73cbe1931dad7d1f5fea8b72e650555 Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Mon, 7 Apr 2025 11:10:42 +0200 Subject: [PATCH 1/2] Filter out empty top docs results before merging `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 --- .../elasticsearch/action/search/SearchPhaseController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java index 958d3e83a21f6..ec9e70507954a 100644 --- a/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java +++ b/server/src/main/java/org/elasticsearch/action/search/SearchPhaseController.java @@ -150,11 +150,11 @@ static TopDocs mergeTopDocs(List results, int topN, int from) { 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]); From 2e4d9dc0a373e8ca5056c917d84816dc3009e20b Mon Sep 17 00:00:00 2001 From: Luca Cavanna Date: Mon, 7 Apr 2025 11:18:16 +0200 Subject: [PATCH 2/2] Update docs/changelog/126385.yaml --- docs/changelog/126385.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/126385.yaml diff --git a/docs/changelog/126385.yaml b/docs/changelog/126385.yaml new file mode 100644 index 0000000000000..c59d1f15c6eae --- /dev/null +++ b/docs/changelog/126385.yaml @@ -0,0 +1,6 @@ +pr: 126385 +summary: Filter out empty top docs results before merging +area: Search +type: bug +issues: + - 126118