Skip to content

Commit be25897

Browse files
committed
collapse using a single pass
1 parent b476ad0 commit be25897

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

server/src/main/java/org/elasticsearch/search/vectors/RescoreKnnVectorQuery.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
import org.apache.lucene.search.QueryVisitor;
2121
import org.apache.lucene.search.Scorable;
2222
import org.apache.lucene.search.ScoreDoc;
23+
import org.apache.lucene.search.Sort;
2324
import org.apache.lucene.search.TopDocs;
2425
import org.apache.lucene.search.TotalHits;
26+
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
2527
import org.apache.lucene.search.grouping.GroupSelector;
26-
import org.apache.lucene.search.grouping.GroupingSearch;
2728
import org.apache.lucene.search.grouping.SearchGroup;
28-
import org.apache.lucene.search.grouping.TopGroups;
2929
import org.apache.lucene.search.join.BitSetProducer;
3030
import org.apache.lucene.util.BitSet;
3131
import org.elasticsearch.core.Nullable;
@@ -217,18 +217,22 @@ private LateRescoreQuery(
217217
record DocAndParent(int parent, int doc) {}
218218

219219
@Override
220+
@SuppressWarnings("unchecked")
220221
public Query rewrite(IndexSearcher searcher) throws IOException {
221222
final TopDocs topDocs;
222223
if (parentFilter != null) {
223224
// We're dealing with a nested field, so we need to search at the child level.
224225
// We retrieve the top `rescoreK` child documents, but collapse them so that only
225226
// the best child per parent is kept.
226-
var groupSearch = new GroupingSearch(new ParentSelector(parentFilter));
227-
TopGroups<DocAndParent> topGroups = groupSearch.search(searcher, innerQuery, 0, rescoreK);
228-
var scoreDocs = Arrays.stream(topGroups.groups)
229-
.map(g -> new ScoreDoc(g.groupValue().doc, g.score()))
230-
.toArray(ScoreDoc[]::new);
231-
topDocs = new TopDocs(new TotalHits(topGroups.totalHitCount, TotalHits.Relation.EQUAL_TO), scoreDocs);
227+
FirstPassGroupingCollector<ParentAndDoc> groupingCollector = new FirstPassGroupingCollector<>(
228+
new ParentSelector(parentFilter),
229+
Sort.RELEVANCE,
230+
rescoreK
231+
);
232+
searcher.search(innerQuery, groupingCollector);
233+
var groups = groupingCollector.getTopGroups(0);
234+
var scoreDocs = groups.stream().map(g -> new ScoreDoc(g.groupValue.doc, (float) g.sortValues[0])).toArray(ScoreDoc[]::new);
235+
topDocs = new TopDocs(new TotalHits(scoreDocs.length, TotalHits.Relation.EQUAL_TO), scoreDocs);
232236
} else {
233237
// Retrieve top `rescoreK` documents from the inner query
234238
topDocs = searcher.search(innerQuery, rescoreK);

0 commit comments

Comments
 (0)