From 70a7363fdb2ab12feac7ab10065198602291594a Mon Sep 17 00:00:00 2001
From: Martijn van Groningen
Date: Thu, 6 Oct 2011 20:09:36 +0000
Subject: [PATCH] LUCENE-3483: Move Function grouping collectors from Solr to
grouping module.
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1179808 13f79535-47bb-0310-9956-ffa450edef68
---
dev-tools/idea/modules/grouping/grouping.iml | 1 +
.../index/values/VarSortedBytesImpl.java | 1 +
modules/build.xml | 14 +-
modules/grouping/CHANGES.txt | 5 +
modules/grouping/build.xml | 16 +-
.../grouping/BlockGroupingCollector.java | 2 +-
.../search/grouping/SentinelIntSet.java | 8 +-
.../FunctionAllGroupHeadsCollector.java | 147 ++++++++++++
.../function/FunctionAllGroupsCollector.java | 86 +++++++
.../FunctionFirstPassGroupingCollector.java | 88 +++++++
.../FunctionSecondPassGroupingCollector.java | 85 +++++++
.../lucene/search/grouping/package.html | 10 +-
.../TermAllGroupHeadsCollector.java | 8 +-
.../{ => term}/TermAllGroupsCollector.java | 4 +-
.../TermFirstPassGroupingCollector.java | 5 +-
.../TermSecondPassGroupingCollector.java | 9 +-
...t.java => AllGroupHeadsCollectorTest.java} | 30 ++-
...rTest.java => AllGroupsCollectorTest.java} | 25 +-
.../lucene/search/grouping/TestGrouping.java | 202 ++++++++++++++--
.../valuesource/BytesRefFieldSource.java | 58 +++++
.../org/apache/solr/request/SimpleFacets.java | 4 -
.../java/org/apache/solr/search/Grouping.java | 219 +-----------------
.../solr/search/grouping/CommandHandler.java | 3 +-
.../command/SearchGroupsFieldCommand.java | 2 +-
.../command/TopGroupsFieldCommand.java | 4 +-
25 files changed, 757 insertions(+), 279 deletions(-)
create mode 100644 modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
create mode 100644 modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
create mode 100644 modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
create mode 100644 modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
rename modules/grouping/src/java/org/apache/lucene/search/grouping/{ => term}/TermAllGroupHeadsCollector.java (98%)
rename modules/grouping/src/java/org/apache/lucene/search/grouping/{ => term}/TermAllGroupsCollector.java (95%)
rename modules/grouping/src/java/org/apache/lucene/search/grouping/{ => term}/TermFirstPassGroupingCollector.java (92%)
rename modules/grouping/src/java/org/apache/lucene/search/grouping/{ => term}/TermSecondPassGroupingCollector.java (88%)
rename modules/grouping/src/test/org/apache/lucene/search/grouping/{TermAllGroupHeadsCollectorTest.java => AllGroupHeadsCollectorTest.java} (93%)
rename modules/grouping/src/test/org/apache/lucene/search/grouping/{TermAllGroupsCollectorTest.java => AllGroupsCollectorTest.java} (81%)
create mode 100644 modules/queries/src/java/org/apache/lucene/queries/function/valuesource/BytesRefFieldSource.java
diff --git a/dev-tools/idea/modules/grouping/grouping.iml b/dev-tools/idea/modules/grouping/grouping.iml
index bbd6eabbd4e..2e0b6ff146b 100644
--- a/dev-tools/idea/modules/grouping/grouping.iml
+++ b/dev-tools/idea/modules/grouping/grouping.iml
@@ -12,5 +12,6 @@
+
diff --git a/lucene/src/java/org/apache/lucene/index/values/VarSortedBytesImpl.java b/lucene/src/java/org/apache/lucene/index/values/VarSortedBytesImpl.java
index 36caf0b5082..e352807b033 100644
--- a/lucene/src/java/org/apache/lucene/index/values/VarSortedBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/index/values/VarSortedBytesImpl.java
@@ -30,6 +30,7 @@ import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Counter;
+import org.apache.lucene.util.packed.Direct64;
import org.apache.lucene.util.packed.PackedInts;
// Stores variable-length byte[] by deref, ie when two docs
diff --git a/modules/build.xml b/modules/build.xml
index 62db70ab0ed..6e7dc8c4d43 100644
--- a/modules/build.xml
+++ b/modules/build.xml
@@ -25,9 +25,9 @@
+
-
@@ -40,9 +40,9 @@
+
-
@@ -55,9 +55,9 @@
+
-
@@ -70,9 +70,9 @@
+
-
@@ -86,9 +86,9 @@
+
-
@@ -100,9 +100,9 @@
+
-
@@ -116,9 +116,9 @@
+
-
diff --git a/modules/grouping/CHANGES.txt b/modules/grouping/CHANGES.txt
index 68e0cce51b6..014e77dd402 100644
--- a/modules/grouping/CHANGES.txt
+++ b/modules/grouping/CHANGES.txt
@@ -9,3 +9,8 @@ Optimizations
LUCENE-3468: Replaced last() and remove() with pollLast() in
FirstPassGroupingCollector (Martijn van Groningen)
+
+API Changes
+
+LUCENE-3483: Move Function grouping collectors from Solr to
+ grouping module. (Martijn van Groningen)
diff --git a/modules/grouping/build.xml b/modules/grouping/build.xml
index 6aee1915476..b71f9d6b2c2 100644
--- a/modules/grouping/build.xml
+++ b/modules/grouping/build.xml
@@ -18,8 +18,9 @@
-->
+
- Collectors for grouping search results
+ Grouping module. Collectors for grouping search results
@@ -29,5 +30,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
index 453607c3175..6f38fa6b666 100644
--- a/modules/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/BlockGroupingCollector.java
@@ -49,7 +49,7 @@ import org.apache.lucene.util.PriorityQueue;
* being that the documents in each group must always be
* indexed as a block. This collector also fills in
* TopGroups.totalGroupCount without requiring the separate
- * {@link TermAllGroupsCollector}. However, this collector does
+ * {@link org.apache.lucene.search.grouping.term.TermAllGroupsCollector}. However, this collector does
* not fill in the groupValue of each group; this field
* will always be null.
*
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/SentinelIntSet.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/SentinelIntSet.java
index 21da977fc95..a9c637027c2 100644
--- a/modules/grouping/src/java/org/apache/lucene/search/grouping/SentinelIntSet.java
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/SentinelIntSet.java
@@ -19,8 +19,12 @@ package org.apache.lucene.search.grouping;
import java.util.Arrays;
-/** A native int set where one value is reserved to mean "EMPTY" */
-class SentinelIntSet {
+/**
+ * A native int set where one value is reserved to mean "EMPTY"
+ *
+ * @lucene.internal
+ */
+public class SentinelIntSet {
public int[] keys;
public int count;
public final int emptyVal;
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
new file mode 100644
index 00000000000..6acc90cf80a
--- /dev/null
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupHeadsCollector.java
@@ -0,0 +1,147 @@
+package org.apache.lucene.search.grouping.function;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queries.function.DocValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.FieldComparator;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector;
+import org.apache.lucene.util.mutable.MutableValue;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An implementation of {@link AbstractAllGroupHeadsCollector} for retrieving the most relevant groups when grouping
+ * by {@link ValueSource}.
+ *
+ * @lucene.experimental
+ */
+public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollector {
+
+ private final ValueSource groupBy;
+ private final Map vsContext;
+ private final Map groups;
+ private final Sort sortWithinGroup;
+
+ private DocValues.ValueFiller filler;
+ private MutableValue mval;
+ private IndexReader.AtomicReaderContext readerContext;
+ private Scorer scorer;
+
+ /**
+ * Constructs a {@link FunctionAllGroupHeadsCollector} instance.
+ *
+ * @param groupBy The {@link ValueSource} to group by
+ * @param vsContext The ValueSource context
+ * @param sortWithinGroup The sort within a group
+ */
+ public FunctionAllGroupHeadsCollector(ValueSource groupBy, Map vsContext, Sort sortWithinGroup) {
+ super(sortWithinGroup.getSort().length);
+ groups = new HashMap();
+ this.sortWithinGroup = sortWithinGroup;
+ this.groupBy = groupBy;
+ this.vsContext = vsContext;
+
+ final SortField[] sortFields = sortWithinGroup.getSort();
+ for (int i = 0; i < sortFields.length; i++) {
+ reversed[i] = sortFields[i].getReverse() ? -1 : 1;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void retrieveGroupHeadAndAddIfNotExist(int doc) throws IOException {
+ filler.fillValue(doc);
+ GroupHead groupHead = groups.get(mval);
+ if (groupHead == null) {
+ MutableValue groupValue = mval.duplicate();
+ groupHead = new GroupHead(groupValue, sortWithinGroup, doc);
+ groups.put(groupValue, groupHead);
+ temporalResult.stop = true;
+ } else {
+ temporalResult.stop = false;
+ }
+ this.temporalResult.groupHead = groupHead;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected Collection getCollectedGroupHeads() {
+ return groups.values();
+ }
+
+ public void setScorer(Scorer scorer) throws IOException {
+ this.scorer = scorer;
+ for (GroupHead groupHead : groups.values()) {
+ for (FieldComparator comparator : groupHead.comparators) {
+ comparator.setScorer(scorer);
+ }
+ }
+ }
+
+ public void setNextReader(IndexReader.AtomicReaderContext context) throws IOException {
+ this.readerContext = context;
+ DocValues docValues = groupBy.getValues(vsContext, context);
+ filler = docValues.getValueFiller();
+ mval = filler.getValue();
+
+ for (GroupHead groupHead : groups.values()) {
+ for (int i = 0; i < groupHead.comparators.length; i++) {
+ groupHead.comparators[i] = groupHead.comparators[i].setNextReader(context);
+ }
+ }
+ }
+
+ class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead {
+
+ final FieldComparator[] comparators;
+
+ private GroupHead(MutableValue groupValue, Sort sort, int doc) throws IOException {
+ super(groupValue, doc + readerContext.docBase);
+ final SortField[] sortFields = sort.getSort();
+ comparators = new FieldComparator[sortFields.length];
+ for (int i = 0; i < sortFields.length; i++) {
+ comparators[i] = sortFields[i].getComparator(1, i).setNextReader(readerContext);
+ comparators[i].setScorer(scorer);
+ comparators[i].copy(0, doc);
+ comparators[i].setBottom(0);
+ }
+ }
+
+ public int compare(int compIDX, int doc) throws IOException {
+ return comparators[compIDX].compareBottom(doc);
+ }
+
+ public void updateDocHead(int doc) throws IOException {
+ for (FieldComparator comparator : comparators) {
+ comparator.copy(0, doc);
+ comparator.setBottom(0);
+ }
+ this.doc = doc + readerContext.docBase;
+ }
+ }
+}
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
new file mode 100644
index 00000000000..f17aba3af25
--- /dev/null
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionAllGroupsCollector.java
@@ -0,0 +1,86 @@
+package org.apache.lucene.search.grouping.function;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queries.function.DocValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
+import org.apache.lucene.util.mutable.MutableValue;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * A collector that collects all groups that match the
+ * query. Only the group value is collected, and the order
+ * is undefined. This collector does not determine
+ * the most relevant document of a group.
+ *
+ *
+ * Implementation detail: Uses {@link ValueSource} and {@link DocValues} to retrieve the
+ * field values to group by.
+ *
+ * @lucene.experimental
+ */
+public class FunctionAllGroupsCollector extends AbstractAllGroupsCollector {
+
+ private final Map vsContext;
+ private final ValueSource groupBy;
+ private final SortedSet groups = new TreeSet();
+
+ private DocValues.ValueFiller filler;
+ private MutableValue mval;
+
+ /**
+ * Constructs a {@link FunctionAllGroupsCollector} instance.
+ *
+ * @param groupBy The {@link ValueSource} to group by
+ * @param vsContext The ValueSource context
+ */
+ public FunctionAllGroupsCollector(ValueSource groupBy, Map vsContext) {
+ this.vsContext = vsContext;
+ this.groupBy = groupBy;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Collection getGroups() {
+ return groups;
+ }
+
+ public void collect(int doc) throws IOException {
+ filler.fillValue(doc);
+ if (!groups.contains(mval)) {
+ groups.add(mval.duplicate());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setNextReader(IndexReader.AtomicReaderContext context) throws IOException {
+ DocValues docValues = groupBy.getValues(vsContext, context);
+ filler = docValues.getValueFiller();
+ mval = filler.getValue();
+ }
+}
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
new file mode 100644
index 00000000000..4ece6223f4e
--- /dev/null
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionFirstPassGroupingCollector.java
@@ -0,0 +1,88 @@
+package org.apache.lucene.search.grouping.function;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queries.function.DocValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector;
+import org.apache.lucene.util.mutable.MutableValue;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Concrete implementation of {@link AbstractFirstPassGroupingCollector} that groups based on
+ * {@link ValueSource} instances.
+ *
+ * @lucene.experimental
+ */
+public class FunctionFirstPassGroupingCollector extends AbstractFirstPassGroupingCollector {
+
+ private final ValueSource groupByVS;
+ private final Map vsContext;
+
+ private DocValues docValues;
+ private DocValues.ValueFiller filler;
+ private MutableValue mval;
+
+ /**
+ * Creates a first pass collector.
+ *
+ * @param groupByVS The {@link ValueSource} instance to group by
+ * @param vsContext The ValueSource context
+ * @param groupSort The {@link Sort} used to sort the
+ * groups. The top sorted document within each group
+ * according to groupSort, determines how that group
+ * sorts against other groups. This must be non-null,
+ * ie, if you want to groupSort by relevance use
+ * Sort.RELEVANCE.
+ * @param topNGroups How many top groups to keep.
+ * @throws IOException When I/O related errors occur
+ */
+ public FunctionFirstPassGroupingCollector(ValueSource groupByVS, Map vsContext, Sort groupSort, int topNGroups) throws IOException {
+ super(groupSort, topNGroups);
+ this.groupByVS = groupByVS;
+ this.vsContext = vsContext;
+ }
+
+ @Override
+ protected MutableValue getDocGroupValue(int doc) {
+ filler.fillValue(doc);
+ return mval;
+ }
+
+ @Override
+ protected MutableValue copyDocGroupValue(MutableValue groupValue, MutableValue reuse) {
+ if (reuse != null) {
+ reuse.copy(groupValue);
+ return reuse;
+ }
+ return groupValue.duplicate();
+ }
+
+ @Override
+ public void setNextReader(IndexReader.AtomicReaderContext readerContext) throws IOException {
+ super.setNextReader(readerContext);
+ docValues = groupByVS.getValues(vsContext, readerContext);
+ filler = docValues.getValueFiller();
+ mval = filler.getValue();
+ }
+
+}
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
new file mode 100644
index 00000000000..a5464701b77
--- /dev/null
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/function/FunctionSecondPassGroupingCollector.java
@@ -0,0 +1,85 @@
+package org.apache.lucene.search.grouping.function;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queries.function.DocValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector;
+import org.apache.lucene.search.grouping.SearchGroup;
+import org.apache.lucene.util.mutable.MutableValue;
+import org.apache.lucene.search.grouping.TopGroups; //javadoc
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Concrete implementation of {@link AbstractSecondPassGroupingCollector} that groups based on
+ * {@link ValueSource} instances.
+ *
+ * @lucene.experimental
+ */
+public class FunctionSecondPassGroupingCollector extends AbstractSecondPassGroupingCollector {
+
+ private final ValueSource groupByVS;
+ private final Map vsContext;
+
+ private DocValues.ValueFiller filler;
+ private MutableValue mval;
+
+ /**
+ * Constructs a {@link FunctionSecondPassGroupingCollector} instance.
+ *
+ * @param searchGroups The {@link SearchGroup} instances collected during the first phase.
+ * @param groupSort The group sort
+ * @param withinGroupSort The sort inside a group
+ * @param maxDocsPerGroup The maximum number of documents to collect inside a group
+ * @param getScores Whether to include the scores
+ * @param getMaxScores Whether to include the maximum score
+ * @param fillSortFields Whether to fill the sort values in {@link TopGroups#withinGroupSort}
+ * @param groupByVS The {@link ValueSource} to group by
+ * @param vsContext The value source context
+ * @throws IOException IOException When I/O related errors occur
+ */
+ public FunctionSecondPassGroupingCollector(Collection> searchGroups, Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields, ValueSource groupByVS, Map vsContext) throws IOException {
+ super(searchGroups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
+ this.groupByVS = groupByVS;
+ this.vsContext = vsContext;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected SearchGroupDocs retrieveGroup(int doc) throws IOException {
+ filler.fillValue(doc);
+ return groupMap.get(mval);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setNextReader(IndexReader.AtomicReaderContext readerContext) throws IOException {
+ super.setNextReader(readerContext);
+ DocValues docValues = groupByVS.getValues(vsContext, readerContext);
+ filler = docValues.getValueFiller();
+ mval = filler.getValue();
+ }
+
+}
diff --git a/modules/grouping/src/java/org/apache/lucene/search/grouping/package.html b/modules/grouping/src/java/org/apache/lucene/search/grouping/package.html
index 4d9e4bc657a..647c2be1993 100644
--- a/modules/grouping/src/java/org/apache/lucene/search/grouping/package.html
+++ b/modules/grouping/src/java/org/apache/lucene/search/grouping/package.html
@@ -44,9 +44,9 @@ field fall into a single group.
The implementation is two-pass: the first pass ({@link
- org.apache.lucene.search.grouping.TermFirstPassGroupingCollector})
+ org.apache.lucene.search.grouping.term.TermFirstPassGroupingCollector})
gathers the top groups, and the second pass ({@link
- org.apache.lucene.search.grouping.TermSecondPassGroupingCollector})
+ org.apache.lucene.search.grouping.term.TermSecondPassGroupingCollector})
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
@@ -179,5 +179,11 @@ fields, FieldCache
, etc.).
FixedBitSet groupHeadsBitSet = c.retrieveGroupHeads(maxDoc)
+
For each of the above collectors there is also a variant that works with ValueSource
instead of
+ of fields. Concretely this means that these variants can work with functions. These variants are slower than
+ there term based counter parts. These implementations are located in the
+ org.apache.lucene.search.grouping.function
package.
+
+