From fec2bda3cf2002c5e1a9236e8630c496fdfb8c84 Mon Sep 17 00:00:00 2001 From: Binlong Gao Date: Mon, 29 Jun 2026 14:41:20 +0800 Subject: [PATCH 1/2] Remove unused public methods in AllGroupHeadsCollector Signed-off-by: Binlong Gao --- lucene/CHANGES.txt | 2 + .../grouping/AllGroupHeadsCollector.java | 42 +------------------ 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 2cf190740d8f..3d6fb116a23c 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -321,6 +321,8 @@ API Changes * GITHUB#16363: Add API to use a custom `DictionarySuggester` instead of hardcoded `GeneratingSuggester` +* GITHUB#16385: Remove unused public methods in AllGroupHeadsCollector. (Binlong Gao) + New Features --------------------- diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/AllGroupHeadsCollector.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/AllGroupHeadsCollector.java index 04c80c727a3a..5ef4cd19ee4e 100644 --- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/AllGroupHeadsCollector.java +++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/AllGroupHeadsCollector.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.FieldComparator; import org.apache.lucene.search.LeafFieldComparator; @@ -30,7 +29,6 @@ import org.apache.lucene.search.SimpleCollector; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; -import org.apache.lucene.util.FixedBitSet; /** * This collector specializes in collecting the most relevant document (group head) for each group @@ -40,7 +38,7 @@ * * @lucene.experimental */ -@SuppressWarnings({"unchecked", "rawtypes"}) +@SuppressWarnings({"rawtypes"}) public abstract class AllGroupHeadsCollector extends SimpleCollector { private final GroupSelector groupSelector; @@ -79,44 +77,6 @@ private AllGroupHeadsCollector(GroupSelector selector, Sort sort) { this.compIDXEnd = this.reversed.length - 1; } - /** - * @param maxDoc The maxDoc of the top level {@link IndexReader}. - * @return a {@link FixedBitSet} containing all group heads. - */ - public FixedBitSet retrieveGroupHeads(int maxDoc) { - FixedBitSet bitSet = new FixedBitSet(maxDoc); - - Collection> groupHeads = getCollectedGroupHeads(); - for (GroupHead groupHead : groupHeads) { - bitSet.set(groupHead.doc); - } - - return bitSet; - } - - /** - * @return an int array containing all group heads. The size of the array is equal to number of - * collected unique groups. - */ - public int[] retrieveGroupHeads() { - Collection> groupHeads = getCollectedGroupHeads(); - int[] docHeads = new int[groupHeads.size()]; - - int i = 0; - for (GroupHead groupHead : groupHeads) { - docHeads[i++] = groupHead.doc; - } - - return docHeads; - } - - /** - * @return the number of group heads found for a query. - */ - public int groupHeadsSize() { - return getCollectedGroupHeads().size(); - } - /** * Returns the collected group heads. Subsequent calls should return the same group heads. * From 1c030333f12494552a607469bb40e4a66c18897a Mon Sep 17 00:00:00 2001 From: Binlong Gao Date: Wed, 29 Jul 2026 16:38:39 +0800 Subject: [PATCH 2/2] update grouping package info Signed-off-by: Binlong Gao --- lucene/CHANGES.txt | 3 +- .../lucene/search/grouping/package-info.java | 63 +++++++++++-------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 0f0c61bc2b15..13e46fcb585b 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -321,7 +321,8 @@ API Changes * GITHUB#16363: Add API to use a custom `DictionarySuggester` instead of hardcoded `GeneratingSuggester` -* GITHUB#16385: Remove unused public methods in AllGroupHeadsCollector. (Binlong Gao) +* GITHUB#16385: Remove unused public methods in AllGroupHeadsCollector. + Update grouping package info to use CollectorManager instead of Collector. (Binlong Gao) New Features --------------------- diff --git a/lucene/grouping/src/java/org/apache/lucene/search/grouping/package-info.java b/lucene/grouping/src/java/org/apache/lucene/search/grouping/package-info.java index 72bdc9dcc5eb..d93cc5b0ce88 100644 --- a/lucene/grouping/src/java/org/apache/lucene/search/grouping/package-info.java +++ b/lucene/grouping/src/java/org/apache/lucene/search/grouping/package-info.java @@ -47,13 +47,15 @@ * * *

The implementation is two-pass: the first pass ({@link - * org.apache.lucene.search.grouping.FirstPassGroupingCollector}) gathers the top groups, and the - * second pass ({@link org.apache.lucene.search.grouping.SecondPassGroupingCollector}) gathers - * documents within those groups. If the search is costly to run you may want to use the {@link - * org.apache.lucene.search.CachingCollector} class, which caches hits and can (quickly) replay them - * for the second pass. This way you only run the query once, but you pay a RAM cost to (briefly) - * hold all hits. Results are returned as a {@link org.apache.lucene.search.grouping.TopGroups} - * instance. + * org.apache.lucene.search.grouping.FirstPassGroupingCollectorManager}) gathers the top groups, and + * the second pass ({@link org.apache.lucene.search.grouping.TopGroupsCollectorManager}) gathers + * documents within those groups. Both passes use {@link org.apache.lucene.search.CollectorManager} + * to support concurrent (parallel) collection across segments. If the search is costly to run you + * may want to use the {@link org.apache.lucene.search.CachingCollectorManager} class, which wraps + * the first-pass manager and caches all collected documents (and optionally scores) per segment + * slice so they can be replayed into the second-pass manager without re-running the query. This way + * you only run the query once, but you pay a RAM cost to (briefly) hold all hits. Results are + * returned as a {@link org.apache.lucene.search.grouping.TopGroups} instance. * *

Groups are defined by {@link org.apache.lucene.search.grouping.GroupSelector} implementations: * @@ -101,9 +103,9 @@ * } * * - *

To use the single-pass BlockGroupingCollector, first, at indexing time, you must - * ensure all docs in each group are added as a block, and you have some way to find the last - * document of each group. One simple way to do this is to add a marker binary field: + *

To use the single-pass BlockGroupingCollectorManager, first, at indexing time, + * you must ensure all docs in each group are added as a block, and you have some way to find the + * last document of each group. One simple way to do this is to add a marker binary field: * *


  *   // Create Documents from your source:
@@ -125,9 +127,18 @@
  *
  * 

  *   Query groupEndDocs = new TermQuery(new Term("groupEnd", "x"));
- *   BlockGroupingCollector c = new BlockGroupingCollector(groupSort, groupOffset+topNGroups, needsScores, groupEndDocs);
- *   s.search(new TermQuery(new Term("content", searchTerm)), c);
- *   TopGroups groupsResult = c.getTopGroups(withinGroupSort, groupOffset, docOffset, docOffset+docsPerGroup, fillFields);
+ *   Weight lastDocPerGroup = indexSearcher.createWeight(
+ *       indexSearcher.rewrite(groupEndDocs), ScoreMode.COMPLETE_NO_SCORES, 1);
+ *   BlockGroupingCollectorManager<BytesRef> manager = new BlockGroupingCollectorManager<>(
+ *       groupSort,
+ *       groupOffset,
+ *       topNGroups,
+ *       needsScores,
+ *       lastDocPerGroup,
+ *       withinGroupSort,
+ *       docOffset,
+ *       docsPerGroup);
+ *   TopGroups groupsResult = indexSearcher.search(new TermQuery(new Term("content", searchTerm)), manager);
  *
  *   // Render groupsResult...
  * 
@@ -149,22 +160,24 @@ * so if you need to present this value you'll have to separately retrieve it (for example using * stored fields, FieldCache, etc.). * - *

Another collector is the AllGroupHeadsCollector that can be used to retrieve all - * most relevant documents per group. Also known as group heads. This can be useful in situations - * when one wants to compute group based facets / statistics on the complete query result. The - * collector can be executed during the first or second phase. This collector can also be used with - * the GroupingSearch convenience utility, but when if one only wants to compute the - * most relevant documents per group it is better to just use the collector as done here below. + *

Another collector manager is the AllGroupHeadsCollectorManager that can be used + * to retrieve all most relevant documents per group. Also known as group heads. This can be useful + * in situations when one wants to compute group based facets / statistics on the complete query + * result. The manager supports concurrent collection and can also be used with the + * GroupingSearch convenience utility, but when one only wants to compute the most relevant + * documents per group it is better to just use the manager directly as done here below. * *


- *   TermGroupSelector grouper = new TermGroupSelector(groupField);
- *   AllGroupHeadsCollector c = AllGroupHeadsCollector.newCollector(grouper, sortWithinGroup);
- *   s.search(new TermQuery(new Term("content", searchTerm)), c);
+ *   AllGroupHeadsCollectorManager<BytesRef> manager =
+ *       new AllGroupHeadsCollectorManager<>(
+ *           () -> new TermGroupSelector(groupField), sortWithinGroup);
+ *   AllGroupHeadsCollectorManager.GroupHeadsResult result =
+ *       indexSearcher.search(new TermQuery(new Term("content", searchTerm)), manager);
  *   // Return all group heads as int array
- *   int[] groupHeadsArray = c.retrieveGroupHeads()
+ *   int[] groupHeadsArray = result.retrieveGroupHeads();
  *   // Return all group heads as FixedBitSet.
- *   int maxDoc = s.maxDoc();
- *   FixedBitSet groupHeadsBitSet = c.retrieveGroupHeads(maxDoc)
+ *   int maxDoc = indexSearcher.getIndexReader().maxDoc();
+ *   Bits groupHeadsBitSet = result.retrieveGroupHeads(maxDoc);
  * 
*/ package org.apache.lucene.search.grouping;