Skip to content

Commit 16bd2d2

Browse files
committed
parking the progress in a commit
1 parent 67fc2c2 commit 16bd2d2

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

server/src/main/java/org/elasticsearch/search/retriever/RankDocsRetrieverBuilder.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,31 @@ public void extractToSearchSourceBuilder(SearchSourceBuilder searchSourceBuilder
124124
false
125125
);
126126
}
127+
// Set top-level minScore only when not in onlyRankDocs mode
128+
if (effectiveMinScore != RankDocsQueryBuilder.DEFAULT_MIN_SCORE) {
129+
searchSourceBuilder.minScore(effectiveMinScore);
130+
}
127131
} else {
128-
// Pass minScore down to RankDocsQueryBuilder
129-
rankQuery = new RankDocsQueryBuilder(rankDocResults, null, false, effectiveMinScore);
132+
// Pass minScore down to RankDocsQueryBuilder and set onlyRankDocs = true to ensure pre-computed scores are used.
133+
// Filter the results upfront if minScore is set
134+
RankDoc[] finalRankDocs;
135+
if (effectiveMinScore != RankDocsQueryBuilder.DEFAULT_MIN_SCORE) {
136+
finalRankDocs = Arrays.stream(rankDocResults)
137+
.filter(doc -> doc.score >= effectiveMinScore)
138+
.toArray(RankDoc[]::new);
139+
} else {
140+
finalRankDocs = rankDocResults;
141+
}
142+
// Now pass the potentially filtered array and the original minScore
143+
rankQuery = new RankDocsQueryBuilder(finalRankDocs, null, true, effectiveMinScore);
144+
// Do NOT set top-level minScore here, filtering is done above, and RankDocsQuery handles score propagation.
130145
}
131146
rankQuery.queryName(retrieverName());
132147
// ignore prefilters of this level, they were already propagated to children
133148
searchSourceBuilder.query(rankQuery);
134149
if (searchSourceBuilder.size() < 0) {
135150
searchSourceBuilder.size(rankWindowSize);
136151
}
137-
if (sourceHasMinScore()) {
138-
searchSourceBuilder.minScore(effectiveMinScore);
139-
}
140152
if (searchSourceBuilder.size() + searchSourceBuilder.from() > rankDocResults.length) {
141153
searchSourceBuilder.size(Math.max(0, rankDocResults.length - searchSourceBuilder.from()));
142154
}

x-pack/plugin/rank-rrf/src/internalClusterTest/java/org/elasticsearch/xpack/rank/linear/LinearRetrieverIT.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ public void testLinearWithMinScore() {
924924
assertThat(resp.getHits().getAt(2).getId(), equalTo("doc_1"));
925925
assertThat((double) resp.getHits().getAt(2).getScore(), closeTo(10.0f, 0.1f));
926926
assertThat(resp.getHits().getAt(3).getId(), equalTo("doc_3"));
927-
assertThat((double) resp.getHits().getAt(3).getScore(), closeTo(0.0f, 0.1f));
927+
assertThat((double) resp.getHits().getAt(3).getScore(), closeTo(10.0f, 0.1f));
928928
});
929929
}
930930

@@ -994,12 +994,9 @@ public void testLinearWithMinScoreAndNormalization() {
994994
System.out.println("------------------");
995995

996996
// Calculated scores >= 1.5f should only be doc_2(2.0)
997-
// Observed behavior consistently shows 2 hits: doc_2(2.0) and one other doc (doc_1 or doc_3) with score 0.0
998-
assertThat(resp.getHits().getHits().length, equalTo(2));
997+
assertThat(resp.getHits().getHits().length, equalTo(1));
999998
assertThat(resp.getHits().getAt(0).getId(), equalTo("doc_2"));
1000999
assertThat((double) resp.getHits().getAt(0).getScore(), closeTo(2.0f, 0.01f));
1001-
// Assert the second hit has score 0.0, but don't assert its ID due to inconsistency
1002-
assertThat((double) resp.getHits().getAt(1).getScore(), closeTo(0.0f, 0.01f));
10031000
});
10041001
}
10051002

x-pack/plugin/rank-rrf/src/main/java/org/elasticsearch/xpack/rank/linear/LinearRetrieverBuilder.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,16 @@ protected RankDoc[] combineInnerRetrieverResults(List<ScoreDoc[]> rankResults, b
188188
// sort the results based on the final score, tiebreaker based on smaller doc id
189189
LinearRankDoc[] sortedResults = docsToRankResults.values().toArray(LinearRankDoc[]::new);
190190
Arrays.sort(sortedResults);
191+
192+
// Filter results based on minScore
193+
LinearRankDoc[] filteredResults = Arrays.stream(sortedResults)
194+
.filter(doc -> doc.score >= this.minScore)
195+
.toArray(LinearRankDoc[]::new);
196+
191197
// trim the results if needed, otherwise each shard will always return `rank_window_size` results.
192-
LinearRankDoc[] topResults = new LinearRankDoc[Math.min(rankWindowSize, sortedResults.length)];
198+
LinearRankDoc[] topResults = new LinearRankDoc[Math.min(rankWindowSize, filteredResults.length)];
193199
for (int rank = 0; rank < topResults.length; ++rank) {
194-
topResults[rank] = sortedResults[rank];
200+
topResults[rank] = filteredResults[rank];
195201
topResults[rank].rank = rank + 1;
196202
}
197203
return topResults;

0 commit comments

Comments
 (0)