mirror of https://github.com/apache/lucene.git
LUCENE-7617: Grouping collector API cleanup
This commit is contained in:
parent
52f2a77b78
commit
da30f21f5d
|
@ -68,6 +68,12 @@ API Changes
|
|||
* LUCENE-7607: LeafFieldComparator.setScorer and SimpleFieldComparator.setScorer
|
||||
are declared as throwing IOException (Alan Woodward)
|
||||
|
||||
* LUCENE-7617: Collector construction for two-pass grouping queries is
|
||||
abstracted into a new Grouper class, which can be passed as a constructor
|
||||
parameter to GroupingSearch. The abstract base classes for the different
|
||||
grouping Collectors are renamed to remove the Abstract* prefix.
|
||||
(Alan Woodward, Martijn van Groningen)
|
||||
|
||||
New features
|
||||
|
||||
* LUCENE-5867: Added BooleanSimilarity. (Robert Muir, Adrien Grand)
|
||||
|
|
|
@ -29,13 +29,13 @@ import org.apache.lucene.util.FixedBitSet;
|
|||
* @lucene.experimental
|
||||
*/
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroupHeadsCollector.GroupHead> extends SimpleCollector {
|
||||
public abstract class AllGroupHeadsCollector<T> extends SimpleCollector {
|
||||
|
||||
protected final int[] reversed;
|
||||
protected final int compIDXEnd;
|
||||
protected final TemporalResult temporalResult;
|
||||
|
||||
protected AbstractAllGroupHeadsCollector(int numberOfSorts) {
|
||||
protected AllGroupHeadsCollector(int numberOfSorts) {
|
||||
this.reversed = new int[numberOfSorts];
|
||||
this.compIDXEnd = numberOfSorts - 1;
|
||||
temporalResult = new TemporalResult();
|
||||
|
@ -48,7 +48,7 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
public FixedBitSet retrieveGroupHeads(int maxDoc) {
|
||||
FixedBitSet bitSet = new FixedBitSet(maxDoc);
|
||||
|
||||
Collection<GH> groupHeads = getCollectedGroupHeads();
|
||||
Collection<? extends GroupHead<T>> groupHeads = getCollectedGroupHeads();
|
||||
for (GroupHead groupHead : groupHeads) {
|
||||
bitSet.set(groupHead.doc);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
* @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<GH> groupHeads = getCollectedGroupHeads();
|
||||
Collection<? extends GroupHead<T>> groupHeads = getCollectedGroupHeads();
|
||||
int[] docHeads = new int[groupHeads.size()];
|
||||
|
||||
int i = 0;
|
||||
|
@ -96,7 +96,7 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
*
|
||||
* @return the collected group heads
|
||||
*/
|
||||
protected abstract Collection<GH> getCollectedGroupHeads();
|
||||
protected abstract Collection<? extends GroupHead<T>> getCollectedGroupHeads();
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
|
@ -104,7 +104,7 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
if (temporalResult.stop) {
|
||||
return;
|
||||
}
|
||||
GH groupHead = temporalResult.groupHead;
|
||||
GroupHead<T> groupHead = temporalResult.groupHead;
|
||||
|
||||
// Ok now we need to check if the current doc is more relevant then current doc for this group
|
||||
for (int compIDX = 0; ; compIDX++) {
|
||||
|
@ -131,7 +131,7 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
*/
|
||||
protected class TemporalResult {
|
||||
|
||||
public GH groupHead;
|
||||
public GroupHead<T> groupHead;
|
||||
public boolean stop;
|
||||
|
||||
}
|
||||
|
@ -142,12 +142,12 @@ public abstract class AbstractAllGroupHeadsCollector<GH extends AbstractAllGroup
|
|||
*
|
||||
* The group head contains a group value with its associated most relevant document id.
|
||||
*/
|
||||
public static abstract class GroupHead<GROUP_VALUE_TYPE> {
|
||||
public static abstract class GroupHead<T> {
|
||||
|
||||
public final GROUP_VALUE_TYPE groupValue;
|
||||
public final T groupValue;
|
||||
public int doc;
|
||||
|
||||
protected GroupHead(GROUP_VALUE_TYPE groupValue, int doc) {
|
||||
protected GroupHead(T groupValue, int doc) {
|
||||
this.groupValue = groupValue;
|
||||
this.doc = doc;
|
||||
}
|
|
@ -34,7 +34,7 @@ import org.apache.lucene.util.BytesRef;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class AbstractAllGroupsCollector<GROUP_VALUE_TYPE> extends SimpleCollector {
|
||||
public abstract class AllGroupsCollector<T> extends SimpleCollector {
|
||||
|
||||
/**
|
||||
* Returns the total number of groups for the executed search.
|
||||
|
@ -54,7 +54,7 @@ public abstract class AbstractAllGroupsCollector<GROUP_VALUE_TYPE> extends Simpl
|
|||
*
|
||||
* @return the group values
|
||||
*/
|
||||
public abstract Collection<GROUP_VALUE_TYPE> getGroups();
|
||||
public abstract Collection<T> getGroups();
|
||||
|
||||
// Empty not necessary
|
||||
@Override
|
|
@ -19,7 +19,7 @@ package org.apache.lucene.search.grouping;
|
|||
import org.apache.lucene.search.FieldComparator; // javadocs
|
||||
|
||||
/**
|
||||
* Expert: representation of a group in {@link AbstractFirstPassGroupingCollector},
|
||||
* Expert: representation of a group in {@link FirstPassGroupingCollector},
|
||||
* tracking the top doc and {@link FieldComparator} slot.
|
||||
* @lucene.internal */
|
||||
public class CollectedSearchGroup<T> extends SearchGroup<T> {
|
||||
|
|
|
@ -27,25 +27,25 @@ import org.apache.lucene.search.SimpleCollector;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class AbstractDistinctValuesCollector<GC extends AbstractDistinctValuesCollector.GroupCount<?>> extends SimpleCollector {
|
||||
public abstract class DistinctValuesCollector<T> extends SimpleCollector {
|
||||
|
||||
/**
|
||||
* Returns all unique values for each top N group.
|
||||
*
|
||||
* @return all unique values for each top N group
|
||||
*/
|
||||
public abstract List<GC> getGroups();
|
||||
public abstract List<GroupCount<T>> getGroups();
|
||||
|
||||
/**
|
||||
* Returned by {@link AbstractDistinctValuesCollector#getGroups()},
|
||||
* Returned by {@link DistinctValuesCollector#getGroups()},
|
||||
* representing the value and set of distinct values for the group.
|
||||
*/
|
||||
public abstract static class GroupCount<GROUP_VALUE_TYPE> {
|
||||
public static class GroupCount<T> {
|
||||
|
||||
public final GROUP_VALUE_TYPE groupValue;
|
||||
public final Set<GROUP_VALUE_TYPE> uniqueValues;
|
||||
public final T groupValue;
|
||||
public final Set<T> uniqueValues;
|
||||
|
||||
public GroupCount(GROUP_VALUE_TYPE groupValue) {
|
||||
public GroupCount(T groupValue) {
|
||||
this.groupValue = groupValue;
|
||||
this.uniqueValues = new HashSet<>();
|
||||
}
|
|
@ -16,11 +16,20 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.search.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.search.FieldComparator;
|
||||
import org.apache.lucene.search.LeafFieldComparator;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
import org.apache.lucene.search.SimpleCollector;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
|
||||
/** FirstPassGroupingCollector is the first of two passes necessary
|
||||
* to collect grouped hits. This pass gathers the top N sorted
|
||||
|
@ -32,19 +41,19 @@ import java.util.*;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> extends SimpleCollector {
|
||||
abstract public class FirstPassGroupingCollector<T> extends SimpleCollector {
|
||||
|
||||
private final FieldComparator<?>[] comparators;
|
||||
private final LeafFieldComparator[] leafComparators;
|
||||
private final int[] reversed;
|
||||
private final int topNGroups;
|
||||
private final boolean needsScores;
|
||||
private final HashMap<GROUP_VALUE_TYPE, CollectedSearchGroup<GROUP_VALUE_TYPE>> groupMap;
|
||||
private final HashMap<T, CollectedSearchGroup<T>> groupMap;
|
||||
private final int compIDXEnd;
|
||||
|
||||
// Set once we reach topNGroups unique groups:
|
||||
/** @lucene.internal */
|
||||
protected TreeSet<CollectedSearchGroup<GROUP_VALUE_TYPE>> orderedGroups;
|
||||
protected TreeSet<CollectedSearchGroup<T>> orderedGroups;
|
||||
private int docBase;
|
||||
private int spareSlot;
|
||||
|
||||
|
@ -61,7 +70,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
* @throws IOException If I/O related errors occur
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public AbstractFirstPassGroupingCollector(Sort groupSort, int topNGroups) throws IOException {
|
||||
public FirstPassGroupingCollector(Sort groupSort, int topNGroups) throws IOException {
|
||||
if (topNGroups < 1) {
|
||||
throw new IllegalArgumentException("topNGroups must be >= 1 (got " + topNGroups + ")");
|
||||
}
|
||||
|
@ -102,7 +111,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
* @param fillFields Whether to fill to {@link SearchGroup#sortValues}
|
||||
* @return top groups, starting from offset
|
||||
*/
|
||||
public Collection<SearchGroup<GROUP_VALUE_TYPE>> getTopGroups(int groupOffset, boolean fillFields) throws IOException {
|
||||
public Collection<SearchGroup<T>> getTopGroups(int groupOffset, boolean fillFields) throws IOException {
|
||||
|
||||
//System.out.println("FP.getTopGroups groupOffset=" + groupOffset + " fillFields=" + fillFields + " groupMap.size()=" + groupMap.size());
|
||||
|
||||
|
@ -118,15 +127,15 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
buildSortedSet();
|
||||
}
|
||||
|
||||
final Collection<SearchGroup<GROUP_VALUE_TYPE>> result = new ArrayList<>();
|
||||
final Collection<SearchGroup<T>> result = new ArrayList<>();
|
||||
int upto = 0;
|
||||
final int sortFieldCount = comparators.length;
|
||||
for(CollectedSearchGroup<GROUP_VALUE_TYPE> group : orderedGroups) {
|
||||
for(CollectedSearchGroup<T> group : orderedGroups) {
|
||||
if (upto++ < groupOffset) {
|
||||
continue;
|
||||
}
|
||||
//System.out.println(" group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
|
||||
SearchGroup<GROUP_VALUE_TYPE> searchGroup = new SearchGroup<>();
|
||||
SearchGroup<T> searchGroup = new SearchGroup<>();
|
||||
searchGroup.groupValue = group.groupValue;
|
||||
if (fillFields) {
|
||||
searchGroup.sortValues = new Object[sortFieldCount];
|
||||
|
@ -181,9 +190,9 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
// TODO: should we add option to mean "ignore docs that
|
||||
// don't have the group field" (instead of stuffing them
|
||||
// under null group)?
|
||||
final GROUP_VALUE_TYPE groupValue = getDocGroupValue(doc);
|
||||
final T groupValue = getDocGroupValue(doc);
|
||||
|
||||
final CollectedSearchGroup<GROUP_VALUE_TYPE> group = groupMap.get(groupValue);
|
||||
final CollectedSearchGroup<T> group = groupMap.get(groupValue);
|
||||
|
||||
if (group == null) {
|
||||
|
||||
|
@ -198,7 +207,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
// just keep collecting them
|
||||
|
||||
// Add a new CollectedSearchGroup:
|
||||
CollectedSearchGroup<GROUP_VALUE_TYPE> sg = new CollectedSearchGroup<>();
|
||||
CollectedSearchGroup<T> sg = new CollectedSearchGroup<>();
|
||||
sg.groupValue = copyDocGroupValue(groupValue, null);
|
||||
sg.comparatorSlot = groupMap.size();
|
||||
sg.topDoc = docBase + doc;
|
||||
|
@ -219,7 +228,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
|
||||
// We already tested that the document is competitive, so replace
|
||||
// the bottom group with this new group.
|
||||
final CollectedSearchGroup<GROUP_VALUE_TYPE> bottomGroup = orderedGroups.pollLast();
|
||||
final CollectedSearchGroup<T> bottomGroup = orderedGroups.pollLast();
|
||||
assert orderedGroups.size() == topNGroups -1;
|
||||
|
||||
groupMap.remove(bottomGroup.groupValue);
|
||||
|
@ -269,7 +278,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
// Remove before updating the group since lookup is done via comparators
|
||||
// TODO: optimize this
|
||||
|
||||
final CollectedSearchGroup<GROUP_VALUE_TYPE> prevLast;
|
||||
final CollectedSearchGroup<T> prevLast;
|
||||
if (orderedGroups != null) {
|
||||
prevLast = orderedGroups.last();
|
||||
orderedGroups.remove(group);
|
||||
|
@ -338,7 +347,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
* @param doc The specified doc
|
||||
* @return the group value for the specified doc
|
||||
*/
|
||||
protected abstract GROUP_VALUE_TYPE getDocGroupValue(int doc) throws IOException;
|
||||
protected abstract T getDocGroupValue(int doc) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a copy of the specified group value by creating a new instance and copying the value from the specified
|
||||
|
@ -348,7 +357,7 @@ abstract public class AbstractFirstPassGroupingCollector<GROUP_VALUE_TYPE> exten
|
|||
* @param reuse Optionally a reuse instance to prevent a new instance creation
|
||||
* @return a copy of the specified group value
|
||||
*/
|
||||
protected abstract GROUP_VALUE_TYPE copyDocGroupValue(GROUP_VALUE_TYPE groupValue, GROUP_VALUE_TYPE reuse);
|
||||
protected abstract T copyDocGroupValue(T groupValue, T reuse);
|
||||
|
||||
}
|
||||
|
|
@ -21,10 +21,10 @@ import org.apache.lucene.search.ScoreDoc;
|
|||
/** Represents one group in the results.
|
||||
*
|
||||
* @lucene.experimental */
|
||||
public class GroupDocs<GROUP_VALUE_TYPE> {
|
||||
public class GroupDocs<T> {
|
||||
/** The groupField value for all docs in this group; this
|
||||
* may be null if hits did not have the groupField. */
|
||||
public final GROUP_VALUE_TYPE groupValue;
|
||||
public final T groupValue;
|
||||
|
||||
/** Max score in this group */
|
||||
public final float maxScore;
|
||||
|
@ -42,14 +42,14 @@ public class GroupDocs<GROUP_VALUE_TYPE> {
|
|||
public final int totalHits;
|
||||
|
||||
/** Matches the groupSort passed to {@link
|
||||
* AbstractFirstPassGroupingCollector}. */
|
||||
* FirstPassGroupingCollector}. */
|
||||
public final Object[] groupSortValues;
|
||||
|
||||
public GroupDocs(float score,
|
||||
float maxScore,
|
||||
int totalHits,
|
||||
ScoreDoc[] scoreDocs,
|
||||
GROUP_VALUE_TYPE groupValue,
|
||||
T groupValue,
|
||||
Object[] groupSortValues) {
|
||||
this.score = score;
|
||||
this.maxScore = maxScore;
|
||||
|
|
|
@ -16,20 +16,25 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.lucene.search.Scorer;
|
||||
import org.apache.lucene.search.SimpleCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.PriorityQueue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Base class for computing grouped facets.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class AbstractGroupFacetCollector extends SimpleCollector {
|
||||
public abstract class GroupFacetCollector extends SimpleCollector {
|
||||
|
||||
protected final String groupField;
|
||||
protected final String facetField;
|
||||
|
@ -41,7 +46,7 @@ public abstract class AbstractGroupFacetCollector extends SimpleCollector {
|
|||
protected int startFacetOrd;
|
||||
protected int endFacetOrd;
|
||||
|
||||
protected AbstractGroupFacetCollector(String groupField, String facetField, BytesRef facetPrefix) {
|
||||
protected GroupFacetCollector(String groupField, String facetField, BytesRef facetPrefix) {
|
||||
this.groupField = groupField;
|
||||
this.facetField = facetField;
|
||||
this.facetPrefix = facetPrefix;
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.lucene.search.Sort;
|
||||
|
||||
/**
|
||||
* A factory object to create first and second-pass collectors, run by a {@link GroupingSearch}
|
||||
* @param <T> the type the group value
|
||||
*/
|
||||
public abstract class Grouper<T> {
|
||||
|
||||
/**
|
||||
* Create a first-pass collector
|
||||
* @param sort the order in which groups should be returned
|
||||
* @param count how many groups to return
|
||||
*/
|
||||
public abstract FirstPassGroupingCollector<T> getFirstPassCollector(Sort sort, int count) throws IOException;
|
||||
|
||||
/**
|
||||
* Create an {@link AllGroupsCollector}
|
||||
*/
|
||||
public abstract AllGroupsCollector<T> getAllGroupsCollector();
|
||||
|
||||
/**
|
||||
* Create an {@link AllGroupHeadsCollector}
|
||||
* @param sort a within-group sort order to determine which doc is the group head
|
||||
*/
|
||||
public abstract AllGroupHeadsCollector<T> getGroupHeadsCollector(Sort sort);
|
||||
|
||||
/**
|
||||
* Create a second-pass collector
|
||||
*/
|
||||
public abstract SecondPassGroupingCollector<T> getSecondPassCollector(
|
||||
Collection<SearchGroup<T>> groups, Sort groupSort, Sort withinGroupSort,
|
||||
int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields) throws IOException;
|
||||
|
||||
}
|
|
@ -16,6 +16,11 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.CachingCollector;
|
||||
import org.apache.lucene.search.Collector;
|
||||
|
@ -25,25 +30,12 @@ import org.apache.lucene.search.Query;
|
|||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.Weight;
|
||||
import org.apache.lucene.search.grouping.function.FunctionAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionFirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionSecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermFirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermSecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionGrouper;
|
||||
import org.apache.lucene.search.grouping.term.TermGrouper;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Convenience class to perform grouping in a non distributed environment.
|
||||
*
|
||||
|
@ -51,9 +43,7 @@ import java.util.Map;
|
|||
*/
|
||||
public class GroupingSearch {
|
||||
|
||||
private final String groupField;
|
||||
private final ValueSource groupFunction;
|
||||
private final Map<?, ?> valueSourceContext;
|
||||
private final Grouper grouper;
|
||||
private final Query groupEndDocs;
|
||||
|
||||
private Sort groupSort = Sort.RELEVANCE;
|
||||
|
@ -70,7 +60,6 @@ public class GroupingSearch {
|
|||
private boolean cacheScores;
|
||||
private boolean allGroups;
|
||||
private boolean allGroupHeads;
|
||||
private int initialSize = 128;
|
||||
|
||||
private Collection<?> matchingGroups;
|
||||
private Bits matchingGroupHeads;
|
||||
|
@ -82,7 +71,11 @@ public class GroupingSearch {
|
|||
* @param groupField The name of the field to group by.
|
||||
*/
|
||||
public GroupingSearch(String groupField) {
|
||||
this(groupField, null, null, null);
|
||||
this(new TermGrouper(groupField, 128), null);
|
||||
}
|
||||
|
||||
public GroupingSearch(String groupField, int initialSize) {
|
||||
this(new TermGrouper(groupField, initialSize), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,7 +86,7 @@ public class GroupingSearch {
|
|||
* @param valueSourceContext The context of the specified groupFunction
|
||||
*/
|
||||
public GroupingSearch(ValueSource groupFunction, Map<?, ?> valueSourceContext) {
|
||||
this(null, groupFunction, valueSourceContext, null);
|
||||
this(new FunctionGrouper(groupFunction, valueSourceContext), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,13 +96,11 @@ public class GroupingSearch {
|
|||
* @param groupEndDocs The query that marks the last document in all doc blocks
|
||||
*/
|
||||
public GroupingSearch(Query groupEndDocs) {
|
||||
this(null, null, null, groupEndDocs);
|
||||
this(null, groupEndDocs);
|
||||
}
|
||||
|
||||
private GroupingSearch(String groupField, ValueSource groupFunction, Map<?, ?> valueSourceContext, Query groupEndDocs) {
|
||||
this.groupField = groupField;
|
||||
this.groupFunction = groupFunction;
|
||||
this.valueSourceContext = valueSourceContext;
|
||||
private GroupingSearch(Grouper grouper, Query groupEndDocs) {
|
||||
this.grouper = grouper;
|
||||
this.groupEndDocs = groupEndDocs;
|
||||
}
|
||||
|
||||
|
@ -125,7 +116,7 @@ public class GroupingSearch {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> TopGroups<T> search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit) throws IOException {
|
||||
if (groupField != null || groupFunction != null) {
|
||||
if (grouper != null) {
|
||||
return groupByFieldOrFunction(searcher, query, groupOffset, groupLimit);
|
||||
} else if (groupEndDocs != null) {
|
||||
return (TopGroups<T>) groupByDocBlock(searcher, query, groupOffset, groupLimit);
|
||||
|
@ -137,49 +128,13 @@ public class GroupingSearch {
|
|||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected TopGroups groupByFieldOrFunction(IndexSearcher searcher, Query query, int groupOffset, int groupLimit) throws IOException {
|
||||
int topN = groupOffset + groupLimit;
|
||||
final AbstractFirstPassGroupingCollector firstPassCollector;
|
||||
final AbstractAllGroupsCollector allGroupsCollector;
|
||||
final AbstractAllGroupHeadsCollector allGroupHeadsCollector;
|
||||
if (groupFunction != null) {
|
||||
firstPassCollector = new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
|
||||
if (allGroups) {
|
||||
allGroupsCollector = new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
|
||||
} else {
|
||||
allGroupsCollector = null;
|
||||
}
|
||||
if (allGroupHeads) {
|
||||
allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(groupFunction, valueSourceContext, sortWithinGroup);
|
||||
} else {
|
||||
allGroupHeadsCollector = null;
|
||||
}
|
||||
} else {
|
||||
firstPassCollector = new TermFirstPassGroupingCollector(groupField, groupSort, topN);
|
||||
if (allGroups) {
|
||||
allGroupsCollector = new TermAllGroupsCollector(groupField, initialSize);
|
||||
} else {
|
||||
allGroupsCollector = null;
|
||||
}
|
||||
if (allGroupHeads) {
|
||||
allGroupHeadsCollector = TermAllGroupHeadsCollector.create(groupField, sortWithinGroup, initialSize);
|
||||
} else {
|
||||
allGroupHeadsCollector = null;
|
||||
}
|
||||
}
|
||||
|
||||
final Collector firstRound;
|
||||
if (allGroupHeads || allGroups) {
|
||||
List<Collector> collectors = new ArrayList<>();
|
||||
collectors.add(firstPassCollector);
|
||||
if (allGroups) {
|
||||
collectors.add(allGroupsCollector);
|
||||
}
|
||||
if (allGroupHeads) {
|
||||
collectors.add(allGroupHeadsCollector);
|
||||
}
|
||||
firstRound = MultiCollector.wrap(collectors.toArray(new Collector[collectors.size()]));
|
||||
} else {
|
||||
firstRound = firstPassCollector;
|
||||
}
|
||||
final FirstPassGroupingCollector firstPassCollector = grouper.getFirstPassCollector(groupSort, topN);
|
||||
final AllGroupsCollector allGroupsCollector = allGroups ? grouper.getAllGroupsCollector() : null;
|
||||
final AllGroupHeadsCollector allGroupHeadsCollector
|
||||
= allGroupHeads ? grouper.getGroupHeadsCollector(sortWithinGroup) : null;
|
||||
|
||||
final Collector firstRound = MultiCollector.wrap(firstPassCollector, allGroupsCollector, allGroupHeadsCollector);
|
||||
|
||||
CachingCollector cachedCollector = null;
|
||||
if (maxCacheRAMMB != null || maxDocsToCache != null) {
|
||||
|
@ -193,16 +148,9 @@ public class GroupingSearch {
|
|||
searcher.search(query, firstRound);
|
||||
}
|
||||
|
||||
if (allGroups) {
|
||||
matchingGroups = allGroupsCollector.getGroups();
|
||||
} else {
|
||||
matchingGroups = Collections.emptyList();
|
||||
}
|
||||
if (allGroupHeads) {
|
||||
matchingGroupHeads = allGroupHeadsCollector.retrieveGroupHeads(searcher.getIndexReader().maxDoc());
|
||||
} else {
|
||||
matchingGroupHeads = new Bits.MatchNoBits(searcher.getIndexReader().maxDoc());
|
||||
}
|
||||
matchingGroups = allGroups ? allGroupsCollector.getGroups() : Collections.emptyList();
|
||||
matchingGroupHeads = allGroupHeads ? allGroupHeadsCollector.retrieveGroupHeads(searcher.getIndexReader().maxDoc())
|
||||
: new Bits.MatchNoBits(searcher.getIndexReader().maxDoc());
|
||||
|
||||
Collection<SearchGroup> topSearchGroups = firstPassCollector.getTopGroups(groupOffset, fillSortFields);
|
||||
if (topSearchGroups == null) {
|
||||
|
@ -210,12 +158,9 @@ public class GroupingSearch {
|
|||
}
|
||||
|
||||
int topNInsideGroup = groupDocsOffset + groupDocsLimit;
|
||||
AbstractSecondPassGroupingCollector secondPassCollector;
|
||||
if (groupFunction != null) {
|
||||
secondPassCollector = new FunctionSecondPassGroupingCollector((Collection) topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext);
|
||||
} else {
|
||||
secondPassCollector = new TermSecondPassGroupingCollector(groupField, (Collection) topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields);
|
||||
}
|
||||
SecondPassGroupingCollector secondPassCollector
|
||||
= grouper.getSecondPassCollector(topSearchGroups, groupSort, sortWithinGroup, topNInsideGroup,
|
||||
includeScores, includeMaxScore, fillSortFields);
|
||||
|
||||
if (cachedCollector != null && cachedCollector.isCached()) {
|
||||
cachedCollector.replay(secondPassCollector);
|
||||
|
@ -411,19 +356,4 @@ public class GroupingSearch {
|
|||
return matchingGroupHeads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial size of some internal used data structures.
|
||||
* This prevents growing data structures many times. This can improve the performance of the grouping at the cost of
|
||||
* more initial RAM.
|
||||
* <p>
|
||||
* The {@link #setAllGroups} and {@link #setAllGroupHeads} features use this option.
|
||||
* Defaults to 128.
|
||||
*
|
||||
* @param initialSize The initial size of some internal used data structures
|
||||
* @return <code>this</code>
|
||||
*/
|
||||
public GroupingSearch setInitialSize(int initialSize) {
|
||||
this.initialSize = initialSize;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,28 +16,37 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.apache.lucene.search.FieldComparator;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Represents a group that is found during the first pass search.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class SearchGroup<GROUP_VALUE_TYPE> {
|
||||
public class SearchGroup<T> {
|
||||
|
||||
/** The value that defines this group */
|
||||
public GROUP_VALUE_TYPE groupValue;
|
||||
public T groupValue;
|
||||
|
||||
/** The sort values used during sorting. These are the
|
||||
* groupSort field values of the highest rank document
|
||||
* (by the groupSort) within the group. Can be
|
||||
* <code>null</code> if <code>fillFields=false</code> had
|
||||
* been passed to {@link AbstractFirstPassGroupingCollector#getTopGroups} */
|
||||
* been passed to {@link FirstPassGroupingCollector#getTopGroups} */
|
||||
public Object[] sortValues;
|
||||
|
||||
@Override
|
||||
|
@ -327,7 +336,7 @@ public class SearchGroup<GROUP_VALUE_TYPE> {
|
|||
* groupSort must match how the groups were sorted, and
|
||||
* the provided SearchGroups must have been computed
|
||||
* with fillFields=true passed to {@link
|
||||
* AbstractFirstPassGroupingCollector#getTopGroups}.
|
||||
* FirstPassGroupingCollector#getTopGroups}.
|
||||
*
|
||||
* <p>NOTE: this returns null if the topGroups is empty.
|
||||
*/
|
||||
|
|
|
@ -16,15 +16,22 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.search.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.search.LeafCollector;
|
||||
import org.apache.lucene.search.Scorer;
|
||||
import org.apache.lucene.search.SimpleCollector;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.search.TopDocsCollector;
|
||||
import org.apache.lucene.search.TopFieldCollector;
|
||||
import org.apache.lucene.search.TopScoreDocCollector;
|
||||
|
||||
/**
|
||||
* SecondPassGroupingCollector is the second of two passes
|
||||
* necessary to collect grouped docs. This pass gathers the
|
||||
|
@ -37,22 +44,22 @@ import java.util.Objects;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> extends SimpleCollector {
|
||||
public abstract class SecondPassGroupingCollector<T> extends SimpleCollector {
|
||||
|
||||
private final Collection<SearchGroup<GROUP_VALUE_TYPE>> groups;
|
||||
private final Collection<SearchGroup<T>> groups;
|
||||
private final Sort groupSort;
|
||||
private final Sort withinGroupSort;
|
||||
private final int maxDocsPerGroup;
|
||||
private final boolean needsScores;
|
||||
protected final Map<GROUP_VALUE_TYPE, SearchGroupDocs<GROUP_VALUE_TYPE>> groupMap;
|
||||
protected final Map<T, SearchGroupDocs<T>> groupMap;
|
||||
|
||||
protected SearchGroupDocs<GROUP_VALUE_TYPE>[] groupDocs;
|
||||
protected SearchGroupDocs<T>[] groupDocs;
|
||||
|
||||
private int totalHitCount;
|
||||
private int totalGroupedHitCount;
|
||||
|
||||
public AbstractSecondPassGroupingCollector(Collection<SearchGroup<GROUP_VALUE_TYPE>> groups, Sort groupSort, Sort withinGroupSort,
|
||||
int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields)
|
||||
public SecondPassGroupingCollector(Collection<SearchGroup<T>> groups, Sort groupSort, Sort withinGroupSort,
|
||||
int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields)
|
||||
throws IOException {
|
||||
|
||||
//System.out.println("SP init");
|
||||
|
@ -67,7 +74,7 @@ public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> exte
|
|||
this.needsScores = getScores || getMaxScores || withinGroupSort.needsScores();
|
||||
|
||||
this.groupMap = new HashMap<>(groups.size());
|
||||
for (SearchGroup<GROUP_VALUE_TYPE> group : groups) {
|
||||
for (SearchGroup<T> group : groups) {
|
||||
//System.out.println(" prep group=" + (group.groupValue == null ? "null" : group.groupValue.utf8ToString()));
|
||||
final TopDocsCollector<?> collector;
|
||||
if (withinGroupSort.equals(Sort.RELEVANCE)) { // optimize to use TopScoreDocCollector
|
||||
|
@ -88,7 +95,7 @@ public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> exte
|
|||
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
for (SearchGroupDocs<GROUP_VALUE_TYPE> group : groupMap.values()) {
|
||||
for (SearchGroupDocs<T> group : groupMap.values()) {
|
||||
group.leafCollector.setScorer(scorer);
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +103,7 @@ public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> exte
|
|||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
totalHitCount++;
|
||||
SearchGroupDocs<GROUP_VALUE_TYPE> group = retrieveGroup(doc);
|
||||
SearchGroupDocs<T> group = retrieveGroup(doc);
|
||||
if (group != null) {
|
||||
totalGroupedHitCount++;
|
||||
group.leafCollector.collect(doc);
|
||||
|
@ -110,24 +117,24 @@ public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> exte
|
|||
* @return the group the specified doc belongs to or <code>null</code> if no group could be retrieved
|
||||
* @throws IOException If an I/O related error occurred
|
||||
*/
|
||||
protected abstract SearchGroupDocs<GROUP_VALUE_TYPE> retrieveGroup(int doc) throws IOException;
|
||||
protected abstract SearchGroupDocs<T> retrieveGroup(int doc) throws IOException;
|
||||
|
||||
@Override
|
||||
protected void doSetNextReader(LeafReaderContext readerContext) throws IOException {
|
||||
//System.out.println("SP.setNextReader");
|
||||
for (SearchGroupDocs<GROUP_VALUE_TYPE> group : groupMap.values()) {
|
||||
for (SearchGroupDocs<T> group : groupMap.values()) {
|
||||
group.leafCollector = group.collector.getLeafCollector(readerContext);
|
||||
}
|
||||
}
|
||||
|
||||
public TopGroups<GROUP_VALUE_TYPE> getTopGroups(int withinGroupOffset) {
|
||||
public TopGroups<T> getTopGroups(int withinGroupOffset) {
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
final GroupDocs<GROUP_VALUE_TYPE>[] groupDocsResult = (GroupDocs<GROUP_VALUE_TYPE>[]) new GroupDocs[groups.size()];
|
||||
final GroupDocs<T>[] groupDocsResult = (GroupDocs<T>[]) new GroupDocs[groups.size()];
|
||||
|
||||
int groupIDX = 0;
|
||||
float maxScore = Float.MIN_VALUE;
|
||||
for(SearchGroup<?> group : groups) {
|
||||
final SearchGroupDocs<GROUP_VALUE_TYPE> groupDocs = groupMap.get(group.groupValue);
|
||||
final SearchGroupDocs<T> groupDocs = groupMap.get(group.groupValue);
|
||||
final TopDocs topDocs = groupDocs.collector.topDocs(withinGroupOffset, maxDocsPerGroup);
|
||||
groupDocsResult[groupIDX++] = new GroupDocs<>(Float.NaN,
|
||||
topDocs.getMaxScore(),
|
||||
|
@ -148,13 +155,13 @@ public abstract class AbstractSecondPassGroupingCollector<GROUP_VALUE_TYPE> exte
|
|||
// TODO: merge with SearchGroup or not?
|
||||
// ad: don't need to build a new hashmap
|
||||
// disad: blows up the size of SearchGroup if we need many of them, and couples implementations
|
||||
public class SearchGroupDocs<GROUP_VALUE_TYPE> {
|
||||
public class SearchGroupDocs<T> {
|
||||
|
||||
public final GROUP_VALUE_TYPE groupValue;
|
||||
public final T groupValue;
|
||||
public final TopDocsCollector<?> collector;
|
||||
public LeafCollector leafCollector;
|
||||
|
||||
public SearchGroupDocs(GROUP_VALUE_TYPE groupValue, TopDocsCollector<?> collector) {
|
||||
public SearchGroupDocs(T groupValue, TopDocsCollector<?> collector) {
|
||||
this.groupValue = groupValue;
|
||||
this.collector = collector;
|
||||
}
|
|
@ -16,18 +16,18 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.SortField;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.search.TopFieldDocs;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** Represents result returned by a grouping search.
|
||||
*
|
||||
* @lucene.experimental */
|
||||
public class TopGroups<GROUP_VALUE_TYPE> {
|
||||
public class TopGroups<T> {
|
||||
/** Number of documents matching the search */
|
||||
public final int totalHitCount;
|
||||
|
||||
|
@ -38,7 +38,7 @@ public class TopGroups<GROUP_VALUE_TYPE> {
|
|||
public final Integer totalGroupCount;
|
||||
|
||||
/** Group results in groupSort order */
|
||||
public final GroupDocs<GROUP_VALUE_TYPE>[] groups;
|
||||
public final GroupDocs<T>[] groups;
|
||||
|
||||
/** How groups are sorted against each other */
|
||||
public final SortField[] groupSort;
|
||||
|
@ -50,7 +50,7 @@ public class TopGroups<GROUP_VALUE_TYPE> {
|
|||
* <code>Float.NaN</code> if scores were not computed. */
|
||||
public final float maxScore;
|
||||
|
||||
public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<GROUP_VALUE_TYPE>[] groups, float maxScore) {
|
||||
public TopGroups(SortField[] groupSort, SortField[] withinGroupSort, int totalHitCount, int totalGroupedHitCount, GroupDocs<T>[] groups, float maxScore) {
|
||||
this.groupSort = groupSort;
|
||||
this.withinGroupSort = withinGroupSort;
|
||||
this.totalHitCount = totalHitCount;
|
||||
|
@ -60,7 +60,7 @@ public class TopGroups<GROUP_VALUE_TYPE> {
|
|||
this.maxScore = maxScore;
|
||||
}
|
||||
|
||||
public TopGroups(TopGroups<GROUP_VALUE_TYPE> oldTopGroups, Integer totalGroupCount) {
|
||||
public TopGroups(TopGroups<T> oldTopGroups, Integer totalGroupCount) {
|
||||
this.groupSort = oldTopGroups.groupSort;
|
||||
this.withinGroupSort = oldTopGroups.withinGroupSort;
|
||||
this.totalHitCount = oldTopGroups.totalHitCount;
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping.function;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
|
@ -24,25 +29,20 @@ import org.apache.lucene.search.LeafFieldComparator;
|
|||
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.search.grouping.AllGroupHeadsCollector;
|
||||
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
|
||||
* An implementation of {@link AllGroupHeadsCollector} for retrieving the most relevant groups when grouping
|
||||
* by {@link ValueSource}.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollector<FunctionAllGroupHeadsCollector.GroupHead> {
|
||||
public class FunctionAllGroupHeadsCollector extends AllGroupHeadsCollector<MutableValue> {
|
||||
|
||||
private final ValueSource groupBy;
|
||||
private final Map<?, ?> vsContext;
|
||||
private final Map<MutableValue, GroupHead> groups;
|
||||
private final Map<MutableValue, FunctionGroupHead> groups;
|
||||
private final Sort sortWithinGroup;
|
||||
|
||||
private FunctionValues.ValueFiller filler;
|
||||
|
@ -73,10 +73,10 @@ public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollect
|
|||
@Override
|
||||
protected void retrieveGroupHeadAndAddIfNotExist(int doc) throws IOException {
|
||||
filler.fillValue(doc);
|
||||
GroupHead groupHead = groups.get(mval);
|
||||
FunctionGroupHead groupHead = groups.get(mval);
|
||||
if (groupHead == null) {
|
||||
MutableValue groupValue = mval.duplicate();
|
||||
groupHead = new GroupHead(groupValue, sortWithinGroup, doc);
|
||||
groupHead = new FunctionGroupHead(groupValue, sortWithinGroup, doc);
|
||||
groups.put(groupValue, groupHead);
|
||||
temporalResult.stop = true;
|
||||
} else {
|
||||
|
@ -86,14 +86,14 @@ public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollect
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Collection<GroupHead> getCollectedGroupHeads() {
|
||||
protected Collection<FunctionGroupHead> getCollectedGroupHeads() {
|
||||
return groups.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScorer(Scorer scorer) throws IOException {
|
||||
this.scorer = scorer;
|
||||
for (GroupHead groupHead : groups.values()) {
|
||||
for (FunctionGroupHead groupHead : groups.values()) {
|
||||
for (LeafFieldComparator comparator : groupHead.leafComparators) {
|
||||
comparator.setScorer(scorer);
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollect
|
|||
filler = values.getValueFiller();
|
||||
mval = filler.getValue();
|
||||
|
||||
for (GroupHead groupHead : groups.values()) {
|
||||
for (FunctionGroupHead groupHead : groups.values()) {
|
||||
for (int i = 0; i < groupHead.comparators.length; i++) {
|
||||
groupHead.leafComparators[i] = groupHead.comparators[i].getLeafComparator(context);
|
||||
}
|
||||
|
@ -117,13 +117,13 @@ public class FunctionAllGroupHeadsCollector extends AbstractAllGroupHeadsCollect
|
|||
/** Holds current head document for a single group.
|
||||
*
|
||||
* @lucene.experimental */
|
||||
public class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead<MutableValue> {
|
||||
public class FunctionGroupHead extends AllGroupHeadsCollector.GroupHead<MutableValue> {
|
||||
|
||||
final FieldComparator<?>[] comparators;
|
||||
final LeafFieldComparator[] leafComparators;
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private GroupHead(MutableValue groupValue, Sort sort, int doc) throws IOException {
|
||||
private FunctionGroupHead(MutableValue groupValue, Sort sort, int doc) throws IOException {
|
||||
super(groupValue, doc + readerContext.docBase);
|
||||
final SortField[] sortFields = sort.getSort();
|
||||
comparators = new FieldComparator[sortFields.length];
|
||||
|
|
|
@ -19,7 +19,7 @@ package org.apache.lucene.search.grouping.function;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupsCollector;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -39,7 +39,7 @@ import java.util.TreeSet;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class FunctionAllGroupsCollector extends AbstractAllGroupsCollector<MutableValue> {
|
||||
public class FunctionAllGroupsCollector extends AllGroupsCollector<MutableValue> {
|
||||
|
||||
private final Map<?, ?> vsContext;
|
||||
private final ValueSource groupBy;
|
||||
|
|
|
@ -16,27 +16,31 @@
|
|||
*/
|
||||
package org.apache.lucene.search.grouping.function;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.grouping.AbstractDistinctValuesCollector;
|
||||
import org.apache.lucene.search.grouping.DistinctValuesCollector;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Function based implementation of {@link org.apache.lucene.search.grouping.AbstractDistinctValuesCollector}.
|
||||
* Function based implementation of {@link DistinctValuesCollector}.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class FunctionDistinctValuesCollector extends AbstractDistinctValuesCollector<FunctionDistinctValuesCollector.GroupCount> {
|
||||
public class FunctionDistinctValuesCollector extends DistinctValuesCollector<MutableValue> {
|
||||
|
||||
private final Map<?, ?> vsContext;
|
||||
private final ValueSource groupSource;
|
||||
private final ValueSource countSource;
|
||||
private final Map<MutableValue, GroupCount> groupMap;
|
||||
private final Map<MutableValue, GroupCount<MutableValue>> groupMap;
|
||||
|
||||
private FunctionValues.ValueFiller groupFiller;
|
||||
private FunctionValues.ValueFiller countFiller;
|
||||
|
@ -49,19 +53,19 @@ public class FunctionDistinctValuesCollector extends AbstractDistinctValuesColle
|
|||
this.countSource = countSource;
|
||||
groupMap = new LinkedHashMap<>();
|
||||
for (SearchGroup<MutableValue> group : groups) {
|
||||
groupMap.put(group.groupValue, new GroupCount(group.groupValue));
|
||||
groupMap.put(group.groupValue, new GroupCount<>(group.groupValue));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupCount> getGroups() {
|
||||
public List<GroupCount<MutableValue>> getGroups() {
|
||||
return new ArrayList<>(groupMap.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collect(int doc) throws IOException {
|
||||
groupFiller.fillValue(doc);
|
||||
GroupCount groupCount = groupMap.get(groupMval);
|
||||
GroupCount<MutableValue> groupCount = groupMap.get(groupMval);
|
||||
if (groupCount != null) {
|
||||
countFiller.fillValue(doc);
|
||||
groupCount.uniqueValues.add(countMval.duplicate());
|
||||
|
@ -78,15 +82,4 @@ public class FunctionDistinctValuesCollector extends AbstractDistinctValuesColle
|
|||
countMval = countFiller.getValue();
|
||||
}
|
||||
|
||||
/** Holds distinct values for a single group.
|
||||
*
|
||||
* @lucene.experimental */
|
||||
public static class GroupCount extends AbstractDistinctValuesCollector.GroupCount<MutableValue> {
|
||||
|
||||
GroupCount(MutableValue groupValue) {
|
||||
super(groupValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,19 +20,19 @@ import org.apache.lucene.index.LeafReaderContext;
|
|||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link AbstractFirstPassGroupingCollector} that groups based on
|
||||
* Concrete implementation of {@link FirstPassGroupingCollector} that groups based on
|
||||
* {@link ValueSource} instances.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class FunctionFirstPassGroupingCollector extends AbstractFirstPassGroupingCollector<MutableValue> {
|
||||
public class FunctionFirstPassGroupingCollector extends FirstPassGroupingCollector<MutableValue> {
|
||||
|
||||
private final ValueSource groupByVS;
|
||||
private final Map<?, ?> vsContext;
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.search.grouping.function;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.Grouper;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
|
||||
/**
|
||||
* Collector factory for grouping by ValueSource
|
||||
*/
|
||||
public class FunctionGrouper extends Grouper<MutableValue> {
|
||||
|
||||
private final ValueSource valueSource;
|
||||
private final Map<?, ?> context;
|
||||
|
||||
/**
|
||||
* Create a Grouper for the provided ValueSource and context
|
||||
*/
|
||||
public FunctionGrouper(ValueSource valueSource, Map<?, ?> context) {
|
||||
this.valueSource = valueSource;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FirstPassGroupingCollector<MutableValue> getFirstPassCollector(Sort sort, int count) throws IOException {
|
||||
return new FunctionFirstPassGroupingCollector(valueSource, context, sort, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllGroupHeadsCollector<MutableValue> getGroupHeadsCollector(Sort sort) {
|
||||
return new FunctionAllGroupHeadsCollector(valueSource, context, sort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllGroupsCollector<MutableValue> getAllGroupsCollector() {
|
||||
return new FunctionAllGroupsCollector(valueSource, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecondPassGroupingCollector<MutableValue> getSecondPassCollector(Collection<SearchGroup<MutableValue>> searchGroups, Sort groupSort, Sort withinGroupSort, int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields) throws IOException {
|
||||
return new FunctionSecondPassGroupingCollector(searchGroups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, valueSource, context);
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ import org.apache.lucene.index.LeafReaderContext;
|
|||
import org.apache.lucene.queries.function.FunctionValues;
|
||||
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.SecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.mutable.MutableValue;
|
||||
import org.apache.lucene.search.grouping.TopGroups; //javadoc
|
||||
|
@ -30,12 +30,12 @@ import java.util.Collection;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link AbstractSecondPassGroupingCollector} that groups based on
|
||||
* Concrete implementation of {@link SecondPassGroupingCollector} that groups based on
|
||||
* {@link ValueSource} instances.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class FunctionSecondPassGroupingCollector extends AbstractSecondPassGroupingCollector<MutableValue> {
|
||||
public class FunctionSecondPassGroupingCollector extends SecondPassGroupingCollector<MutableValue> {
|
||||
|
||||
private final ValueSource groupByVS;
|
||||
private final Map<?, ?> vsContext;
|
||||
|
|
|
@ -31,19 +31,19 @@ import org.apache.lucene.search.LeafFieldComparator;
|
|||
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.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.SentinelIntSet;
|
||||
|
||||
/**
|
||||
* A base implementation of {@link org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector} for retrieving the most relevant groups when grouping
|
||||
* A base implementation of {@link AllGroupHeadsCollector} for retrieving the most relevant groups when grouping
|
||||
* on a string based group field. More specifically this all concrete implementations of this base implementation
|
||||
* use {@link SortedDocValues}.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHeadsCollector.GroupHead<?>> extends AbstractAllGroupHeadsCollector<GH> {
|
||||
public abstract class TermAllGroupHeadsCollector extends AllGroupHeadsCollector<BytesRef> {
|
||||
|
||||
private static final int DEFAULT_INITIAL_SIZE = 128;
|
||||
|
||||
|
@ -67,7 +67,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
* @param sortWithinGroup The sort within each group
|
||||
* @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
|
||||
*/
|
||||
public static AbstractAllGroupHeadsCollector<?> create(String groupField, Sort sortWithinGroup) {
|
||||
public static AllGroupHeadsCollector<BytesRef> create(String groupField, Sort sortWithinGroup) {
|
||||
return create(groupField, sortWithinGroup, DEFAULT_INITIAL_SIZE);
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
* 4 bytes * initialSize.
|
||||
* @return an <code>AbstractAllGroupHeadsCollector</code> instance based on the supplied arguments
|
||||
*/
|
||||
public static AbstractAllGroupHeadsCollector<?> create(String groupField, Sort sortWithinGroup, int initialSize) {
|
||||
public static AllGroupHeadsCollector<BytesRef> create(String groupField, Sort sortWithinGroup, int initialSize) {
|
||||
boolean sortAllScore = true;
|
||||
boolean sortAllFieldValue = true;
|
||||
|
||||
|
@ -113,7 +113,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
}
|
||||
|
||||
// A general impl that works for any group sort.
|
||||
static class GeneralAllGroupHeadsCollector extends TermAllGroupHeadsCollector<GeneralAllGroupHeadsCollector.GroupHead> {
|
||||
static class GeneralAllGroupHeadsCollector extends TermAllGroupHeadsCollector {
|
||||
|
||||
private final Sort sortWithinGroup;
|
||||
private final Map<BytesRef, GroupHead> groups;
|
||||
|
@ -199,7 +199,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
}
|
||||
}
|
||||
|
||||
class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
class GroupHead extends AllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
final FieldComparator[] comparators;
|
||||
|
@ -239,7 +239,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
|
||||
|
||||
// AbstractAllGroupHeadsCollector optimized for ord fields and scores.
|
||||
static class OrdScoreAllGroupHeadsCollector extends TermAllGroupHeadsCollector<OrdScoreAllGroupHeadsCollector.GroupHead> {
|
||||
static class OrdScoreAllGroupHeadsCollector extends TermAllGroupHeadsCollector {
|
||||
|
||||
private final SentinelIntSet ordSet;
|
||||
private final List<GroupHead> collectedGroups;
|
||||
|
@ -365,7 +365,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
}
|
||||
}
|
||||
|
||||
class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
class GroupHead extends AllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
|
||||
BytesRefBuilder[] sortValues;
|
||||
int[] sortOrds;
|
||||
|
@ -452,7 +452,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
|
||||
|
||||
// AbstractAllGroupHeadsCollector optimized for ord fields.
|
||||
static class OrdAllGroupHeadsCollector extends TermAllGroupHeadsCollector<OrdAllGroupHeadsCollector.GroupHead> {
|
||||
static class OrdAllGroupHeadsCollector extends TermAllGroupHeadsCollector {
|
||||
|
||||
private final SentinelIntSet ordSet;
|
||||
private final List<GroupHead> collectedGroups;
|
||||
|
@ -566,7 +566,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
}
|
||||
}
|
||||
|
||||
class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
class GroupHead extends AllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
|
||||
BytesRefBuilder[] sortValues;
|
||||
int[] sortOrds;
|
||||
|
@ -635,7 +635,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
|
||||
|
||||
// AbstractAllGroupHeadsCollector optimized for scores.
|
||||
static class ScoreAllGroupHeadsCollector extends TermAllGroupHeadsCollector<ScoreAllGroupHeadsCollector.GroupHead> {
|
||||
static class ScoreAllGroupHeadsCollector extends TermAllGroupHeadsCollector {
|
||||
|
||||
final SentinelIntSet ordSet;
|
||||
final List<GroupHead> collectedGroups;
|
||||
|
@ -727,7 +727,7 @@ public abstract class TermAllGroupHeadsCollector<GH extends AbstractAllGroupHead
|
|||
}
|
||||
}
|
||||
|
||||
class GroupHead extends AbstractAllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
class GroupHead extends AllGroupHeadsCollector.GroupHead<BytesRef> {
|
||||
|
||||
float[] scores;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.List;
|
|||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupsCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.SentinelIntSet;
|
||||
|
||||
|
@ -42,7 +42,7 @@ import org.apache.lucene.util.SentinelIntSet;
|
|||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class TermAllGroupsCollector extends AbstractAllGroupsCollector<BytesRef> {
|
||||
public class TermAllGroupsCollector extends AllGroupsCollector<BytesRef> {
|
||||
|
||||
private static final int DEFAULT_INITIAL_SIZE = 128;
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class TermAllGroupsCollector extends AbstractAllGroupsCollector<BytesRef>
|
|||
private SortedDocValues index;
|
||||
|
||||
/**
|
||||
* Expert: Constructs a {@link AbstractAllGroupsCollector}
|
||||
* Expert: Constructs a {@link AllGroupsCollector}
|
||||
*
|
||||
* @param groupField The field to group by
|
||||
* @param initialSize The initial allocation size of the
|
||||
|
@ -69,7 +69,7 @@ public class TermAllGroupsCollector extends AbstractAllGroupsCollector<BytesRef>
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link AbstractAllGroupsCollector}. This sets the
|
||||
* Constructs a {@link AllGroupsCollector}. This sets the
|
||||
* initial allocation size for the internal int set and group
|
||||
* list to 128.
|
||||
*
|
||||
|
|
|
@ -25,24 +25,24 @@ import java.util.List;
|
|||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.search.grouping.AbstractDistinctValuesCollector;
|
||||
import org.apache.lucene.search.grouping.DistinctValuesCollector;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.SentinelIntSet;
|
||||
|
||||
/**
|
||||
* A term based implementation of {@link org.apache.lucene.search.grouping.AbstractDistinctValuesCollector} that relies
|
||||
* A term based implementation of {@link DistinctValuesCollector} that relies
|
||||
* on {@link SortedDocValues} to count the distinct values per group.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector<TermDistinctValuesCollector.GroupCount> {
|
||||
public class TermDistinctValuesCollector extends DistinctValuesCollector<BytesRef> {
|
||||
|
||||
private final String groupField;
|
||||
private final String countField;
|
||||
private final List<GroupCount> groups;
|
||||
private final List<TermGroupCount> groups;
|
||||
private final SentinelIntSet ordSet;
|
||||
private final GroupCount groupCounts[];
|
||||
private final TermGroupCount groupCounts[];
|
||||
|
||||
private SortedDocValues groupFieldTermIndex;
|
||||
private SortedDocValues countFieldTermIndex;
|
||||
|
@ -59,10 +59,10 @@ public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector
|
|||
this.countField = countField;
|
||||
this.groups = new ArrayList<>(groups.size());
|
||||
for (SearchGroup<BytesRef> group : groups) {
|
||||
this.groups.add(new GroupCount(group.groupValue));
|
||||
this.groups.add(new TermGroupCount(group.groupValue));
|
||||
}
|
||||
ordSet = new SentinelIntSet(groups.size(), -2);
|
||||
groupCounts = new GroupCount[ordSet.keys.length];
|
||||
groupCounts = new TermGroupCount[ordSet.keys.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -81,7 +81,7 @@ public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector
|
|||
return;
|
||||
}
|
||||
|
||||
GroupCount gc = groupCounts[slot];
|
||||
TermGroupCount gc = groupCounts[slot];
|
||||
if (doc > countFieldTermIndex.docID()) {
|
||||
countFieldTermIndex.advance(doc);
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<GroupCount> getGroups() {
|
||||
return groups;
|
||||
public List<GroupCount<BytesRef>> getGroups() {
|
||||
return new ArrayList<>(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,7 +128,7 @@ public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector
|
|||
groupFieldTermIndex = DocValues.getSorted(context.reader(), groupField);
|
||||
countFieldTermIndex = DocValues.getSorted(context.reader(), countField);
|
||||
ordSet.clear();
|
||||
for (GroupCount group : groups) {
|
||||
for (TermGroupCount group : groups) {
|
||||
int groupOrd = group.groupValue == null ? -1 : groupFieldTermIndex.lookupTerm(group.groupValue);
|
||||
if (group.groupValue != null && groupOrd < 0) {
|
||||
continue;
|
||||
|
@ -150,11 +150,11 @@ public class TermDistinctValuesCollector extends AbstractDistinctValuesCollector
|
|||
/** Holds distinct values for a single group.
|
||||
*
|
||||
* @lucene.experimental */
|
||||
public static class GroupCount extends AbstractDistinctValuesCollector.GroupCount<BytesRef> {
|
||||
public static class TermGroupCount extends DistinctValuesCollector.GroupCount<BytesRef> {
|
||||
|
||||
int[] ords;
|
||||
|
||||
GroupCount(BytesRef groupValue) {
|
||||
TermGroupCount(BytesRef groupValue) {
|
||||
super(groupValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,18 +22,18 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector} that groups based on
|
||||
* Concrete implementation of {@link FirstPassGroupingCollector} that groups based on
|
||||
* field values and more specifically uses {@link SortedDocValues}
|
||||
* to collect groups.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class TermFirstPassGroupingCollector extends AbstractFirstPassGroupingCollector<BytesRef> {
|
||||
public class TermFirstPassGroupingCollector extends FirstPassGroupingCollector<BytesRef> {
|
||||
|
||||
private SortedDocValues index;
|
||||
|
||||
|
|
|
@ -25,19 +25,19 @@ import org.apache.lucene.index.LeafReaderContext;
|
|||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.index.SortedSetDocValues;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.search.grouping.AbstractGroupFacetCollector;
|
||||
import org.apache.lucene.search.grouping.GroupFacetCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.BytesRefBuilder;
|
||||
import org.apache.lucene.util.SentinelIntSet;
|
||||
import org.apache.lucene.util.UnicodeUtil;
|
||||
|
||||
/**
|
||||
* An implementation of {@link AbstractGroupFacetCollector} that computes grouped facets based on the indexed terms
|
||||
* An implementation of {@link GroupFacetCollector} that computes grouped facets based on the indexed terms
|
||||
* from DocValues.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public abstract class TermGroupFacetCollector extends AbstractGroupFacetCollector {
|
||||
public abstract class TermGroupFacetCollector extends GroupFacetCollector {
|
||||
|
||||
final List<GroupedFacetHit> groupedFacetHits;
|
||||
final SentinelIntSet segmentGroupedFacetHits;
|
||||
|
@ -190,7 +190,7 @@ public abstract class TermGroupFacetCollector extends AbstractGroupFacetCollecto
|
|||
return new SegmentResult(segmentFacetCounts, segmentTotalCount, facetFieldTermsIndex.termsEnum(), startFacetOrd, endFacetOrd);
|
||||
}
|
||||
|
||||
private static class SegmentResult extends AbstractGroupFacetCollector.SegmentResult {
|
||||
private static class SegmentResult extends GroupFacetCollector.SegmentResult {
|
||||
|
||||
final TermsEnum tenum;
|
||||
|
||||
|
@ -380,7 +380,7 @@ public abstract class TermGroupFacetCollector extends AbstractGroupFacetCollecto
|
|||
return new SegmentResult(segmentFacetCounts, segmentTotalCount, facetFieldNumTerms, facetOrdTermsEnum, startFacetOrd, endFacetOrd);
|
||||
}
|
||||
|
||||
private static class SegmentResult extends AbstractGroupFacetCollector.SegmentResult {
|
||||
private static class SegmentResult extends GroupFacetCollector.SegmentResult {
|
||||
|
||||
final TermsEnum tenum;
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.lucene.search.grouping.term;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.Grouper;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
||||
/**
|
||||
* Collector factory for grouping by term
|
||||
*/
|
||||
public class TermGrouper extends Grouper<BytesRef> {
|
||||
|
||||
private final String field;
|
||||
private final int initialSize;
|
||||
|
||||
/**
|
||||
* Create a new TermGrouper
|
||||
* @param field the field to group on
|
||||
*/
|
||||
public TermGrouper(String field) {
|
||||
this(field, 128);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new TermGrouper
|
||||
* @param field the field to group on
|
||||
* @param initialSize the initial size of various internal datastructures
|
||||
*/
|
||||
public TermGrouper(String field, int initialSize) {
|
||||
this.field = field;
|
||||
this.initialSize = initialSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FirstPassGroupingCollector<BytesRef> getFirstPassCollector(Sort sort, int count) throws IOException {
|
||||
return new TermFirstPassGroupingCollector(field, sort, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllGroupHeadsCollector<BytesRef> getGroupHeadsCollector(Sort sort) {
|
||||
return TermAllGroupHeadsCollector.create(field, sort, initialSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllGroupsCollector<BytesRef> getAllGroupsCollector() {
|
||||
return new TermAllGroupsCollector(field, initialSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecondPassGroupingCollector<BytesRef> getSecondPassCollector(
|
||||
Collection<SearchGroup<BytesRef>> groups, Sort groupSort, Sort withinGroupSort,
|
||||
int maxDocsPerGroup, boolean getScores, boolean getMaxScores, boolean fillSortFields) throws IOException {
|
||||
return new TermSecondPassGroupingCollector(field, groups, groupSort, withinGroupSort, maxDocsPerGroup, getScores, getMaxScores, fillSortFields);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -23,19 +23,19 @@ import org.apache.lucene.index.DocValues;
|
|||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedDocValues;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.SentinelIntSet;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector} that groups based on
|
||||
* Concrete implementation of {@link SecondPassGroupingCollector} that groups based on
|
||||
* field values and more specifically uses {@link SortedDocValues}
|
||||
* to collect grouped docs.
|
||||
*
|
||||
* @lucene.experimental
|
||||
*/
|
||||
public class TermSecondPassGroupingCollector extends AbstractSecondPassGroupingCollector<BytesRef> {
|
||||
public class TermSecondPassGroupingCollector extends SecondPassGroupingCollector<BytesRef> {
|
||||
|
||||
private final String groupField;
|
||||
private final SentinelIntSet ordSet;
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.apache.lucene.search.TermQuery;
|
|||
import org.apache.lucene.search.grouping.function.FunctionAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupHeadsCollector;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.FixedBitSet;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
@ -138,7 +139,7 @@ public class AllGroupHeadsCollectorTest extends LuceneTestCase {
|
|||
int maxDoc = reader.maxDoc();
|
||||
|
||||
Sort sortWithinGroup = new Sort(new SortField("id_1", SortField.Type.INT, true));
|
||||
AbstractAllGroupHeadsCollector<?> allGroupHeadsCollector = createRandomCollector(groupField, sortWithinGroup);
|
||||
AllGroupHeadsCollector<?> allGroupHeadsCollector = createRandomCollector(groupField, sortWithinGroup);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), allGroupHeadsCollector);
|
||||
assertTrue(arrayContains(new int[]{2, 3, 5, 7}, allGroupHeadsCollector.retrieveGroupHeads()));
|
||||
assertTrue(openBitSetContains(new int[]{2, 3, 5, 7}, allGroupHeadsCollector.retrieveGroupHeads(maxDoc), maxDoc));
|
||||
|
@ -326,7 +327,7 @@ public class AllGroupHeadsCollectorTest extends LuceneTestCase {
|
|||
final String searchTerm = "real" + random().nextInt(3);
|
||||
boolean sortByScoreOnly = random().nextBoolean();
|
||||
Sort sortWithinGroup = getRandomSort(sortByScoreOnly);
|
||||
AbstractAllGroupHeadsCollector<?> allGroupHeadsCollector = createRandomCollector("group", sortWithinGroup);
|
||||
AllGroupHeadsCollector<?> allGroupHeadsCollector = createRandomCollector("group", sortWithinGroup);
|
||||
s.search(new TermQuery(new Term("content", searchTerm)), allGroupHeadsCollector);
|
||||
int[] expectedGroupHeads = createExpectedGroupHeads(searchTerm, groupDocs, sortWithinGroup, sortByScoreOnly, fieldIdToDocID);
|
||||
int[] actualGroupHeads = allGroupHeadsCollector.retrieveGroupHeads();
|
||||
|
@ -402,8 +403,9 @@ public class AllGroupHeadsCollectorTest extends LuceneTestCase {
|
|||
return true;
|
||||
}
|
||||
|
||||
private boolean openBitSetContains(int[] expectedDocs, FixedBitSet actual, int maxDoc) throws IOException {
|
||||
if (expectedDocs.length != actual.cardinality()) {
|
||||
private boolean openBitSetContains(int[] expectedDocs, Bits actual, int maxDoc) throws IOException {
|
||||
assert actual instanceof FixedBitSet;
|
||||
if (expectedDocs.length != ((FixedBitSet)actual).cardinality()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -510,8 +512,8 @@ public class AllGroupHeadsCollectorTest extends LuceneTestCase {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private AbstractAllGroupHeadsCollector<?> createRandomCollector(String groupField, Sort sortWithinGroup) {
|
||||
AbstractAllGroupHeadsCollector<? extends AbstractAllGroupHeadsCollector.GroupHead> collector;
|
||||
private AllGroupHeadsCollector<?> createRandomCollector(String groupField, Sort sortWithinGroup) {
|
||||
AllGroupHeadsCollector<?> collector;
|
||||
if (random().nextBoolean()) {
|
||||
ValueSource vs = new BytesRefFieldSource(groupField);
|
||||
collector = new FunctionAllGroupHeadsCollector(vs, new HashMap<>(), sortWithinGroup);
|
||||
|
|
|
@ -102,7 +102,7 @@ public class AllGroupsCollectorTest extends LuceneTestCase {
|
|||
IndexSearcher indexSearcher = newSearcher(w.getReader());
|
||||
w.close();
|
||||
|
||||
AbstractAllGroupsCollector<?> allGroupsCollector = createRandomCollector(groupField);
|
||||
AllGroupsCollector<?> allGroupsCollector = createRandomCollector(groupField);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), allGroupsCollector);
|
||||
assertEquals(4, allGroupsCollector.getGroupCount());
|
||||
|
||||
|
@ -123,8 +123,8 @@ public class AllGroupsCollectorTest extends LuceneTestCase {
|
|||
doc.add(new SortedDocValuesField(groupField, new BytesRef(value)));
|
||||
}
|
||||
|
||||
private AbstractAllGroupsCollector<?> createRandomCollector(String groupField) {
|
||||
AbstractAllGroupsCollector<?> selected;
|
||||
private AllGroupsCollector<?> createRandomCollector(String groupField) {
|
||||
AllGroupsCollector<?> selected;
|
||||
if (random().nextBoolean()) {
|
||||
selected = new TermAllGroupsCollector(groupField);
|
||||
} else {
|
||||
|
|
|
@ -126,10 +126,10 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
IndexSearcher indexSearcher = newSearcher(w.getReader());
|
||||
w.close();
|
||||
|
||||
Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>> cmp = new Comparator<AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>>() {
|
||||
Comparator<DistinctValuesCollector.GroupCount<Comparable<Object>>> cmp = new Comparator<DistinctValuesCollector.GroupCount<Comparable<Object>>>() {
|
||||
|
||||
@Override
|
||||
public int compare(AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount1, AbstractDistinctValuesCollector.GroupCount<Comparable<Object>> groupCount2) {
|
||||
public int compare(DistinctValuesCollector.GroupCount<Comparable<Object>> groupCount1, DistinctValuesCollector.GroupCount<Comparable<Object>> groupCount2) {
|
||||
if (groupCount1.groupValue == null) {
|
||||
if (groupCount2.groupValue == null) {
|
||||
return 0;
|
||||
|
@ -145,13 +145,13 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
};
|
||||
|
||||
// === Search for content:random
|
||||
AbstractFirstPassGroupingCollector<Comparable<Object>> firstCollector = createRandomFirstPassCollector(new Sort(), groupField, 10);
|
||||
FirstPassGroupingCollector<Comparable<Object>> firstCollector = createRandomFirstPassCollector(new Sort(), groupField, 10);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), firstCollector);
|
||||
AbstractDistinctValuesCollector<? extends AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>> distinctValuesCollector
|
||||
DistinctValuesCollector<Comparable<Object>> distinctValuesCollector
|
||||
= createDistinctCountCollector(firstCollector, groupField, countField);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), distinctValuesCollector);
|
||||
|
||||
List<? extends AbstractDistinctValuesCollector.GroupCount<Comparable<Object>>> gcs = distinctValuesCollector.getGroups();
|
||||
List<DistinctValuesCollector.GroupCount<Comparable<Object>>> gcs = distinctValuesCollector.getGroups();
|
||||
Collections.sort(gcs, cmp);
|
||||
assertEquals(4, gcs.size());
|
||||
|
||||
|
@ -240,15 +240,15 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
Sort groupSort = new Sort(new SortField("id", SortField.Type.STRING));
|
||||
int topN = 1 + random.nextInt(10);
|
||||
|
||||
List<AbstractDistinctValuesCollector.GroupCount<Comparable<?>>> expectedResult = createExpectedResult(context, term, groupSort, topN);
|
||||
List<DistinctValuesCollector.GroupCount<Comparable<?>>> expectedResult = createExpectedResult(context, term, groupSort, topN);
|
||||
|
||||
AbstractFirstPassGroupingCollector<Comparable<?>> firstCollector = createRandomFirstPassCollector(groupSort, groupField, topN);
|
||||
FirstPassGroupingCollector<Comparable<?>> firstCollector = createRandomFirstPassCollector(groupSort, groupField, topN);
|
||||
searcher.search(new TermQuery(new Term("content", term)), firstCollector);
|
||||
AbstractDistinctValuesCollector<? extends AbstractDistinctValuesCollector.GroupCount<Comparable<?>>> distinctValuesCollector
|
||||
DistinctValuesCollector<Comparable<?>> distinctValuesCollector
|
||||
= createDistinctCountCollector(firstCollector, groupField, countField);
|
||||
searcher.search(new TermQuery(new Term("content", term)), distinctValuesCollector);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<AbstractDistinctValuesCollector.GroupCount<Comparable<?>>> actualResult = (List<AbstractDistinctValuesCollector.GroupCount<Comparable<?>>>) distinctValuesCollector.getGroups();
|
||||
List<DistinctValuesCollector.GroupCount<Comparable<?>>> actualResult = distinctValuesCollector.getGroups();
|
||||
|
||||
if (VERBOSE) {
|
||||
System.out.println("Index iter=" + indexIter);
|
||||
|
@ -265,8 +265,8 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
|
||||
assertEquals(expectedResult.size(), actualResult.size());
|
||||
for (int i = 0; i < expectedResult.size(); i++) {
|
||||
AbstractDistinctValuesCollector.GroupCount<Comparable<?>> expected = expectedResult.get(i);
|
||||
AbstractDistinctValuesCollector.GroupCount<Comparable<?>> actual = actualResult.get(i);
|
||||
DistinctValuesCollector.GroupCount<Comparable<?>> expected = expectedResult.get(i);
|
||||
DistinctValuesCollector.GroupCount<Comparable<?>> actual = actualResult.get(i);
|
||||
assertValues(expected.groupValue, actual.groupValue);
|
||||
assertEquals(expected.uniqueValues.size(), actual.uniqueValues.size());
|
||||
List<Comparable<?>> expectedUniqueValues = new ArrayList<>(expected.uniqueValues);
|
||||
|
@ -283,9 +283,9 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private void printGroups(List<AbstractDistinctValuesCollector.GroupCount<Comparable<?>>> results) {
|
||||
private void printGroups(List<? extends DistinctValuesCollector.GroupCount<Comparable<?>>> results) {
|
||||
for(int i=0;i<results.size();i++) {
|
||||
AbstractDistinctValuesCollector.GroupCount<Comparable<?>> group = results.get(i);
|
||||
DistinctValuesCollector.GroupCount<Comparable<?>> group = results.get(i);
|
||||
Object gv = group.groupValue;
|
||||
if (gv instanceof BytesRef) {
|
||||
System.out.println(i + ": groupValue=" + ((BytesRef) gv).utf8ToString());
|
||||
|
@ -350,31 +350,31 @@ public class DistinctValuesCollectorTest extends AbstractGroupingTestCase {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private <T extends Comparable> AbstractDistinctValuesCollector<AbstractDistinctValuesCollector.GroupCount<T>> createDistinctCountCollector(AbstractFirstPassGroupingCollector<T> firstPassGroupingCollector,
|
||||
String groupField,
|
||||
String countField) throws IOException {
|
||||
private <T extends Comparable> DistinctValuesCollector<T> createDistinctCountCollector(FirstPassGroupingCollector<T> firstPassGroupingCollector,
|
||||
String groupField,
|
||||
String countField) throws IOException {
|
||||
Random random = random();
|
||||
Collection<SearchGroup<T>> searchGroups = firstPassGroupingCollector.getTopGroups(0, false);
|
||||
if (FunctionFirstPassGroupingCollector.class.isAssignableFrom(firstPassGroupingCollector.getClass())) {
|
||||
return (AbstractDistinctValuesCollector) new FunctionDistinctValuesCollector(new HashMap<>(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), (Collection) searchGroups);
|
||||
return (DistinctValuesCollector) new FunctionDistinctValuesCollector(new HashMap<>(), new BytesRefFieldSource(groupField), new BytesRefFieldSource(countField), (Collection) searchGroups);
|
||||
} else {
|
||||
return (AbstractDistinctValuesCollector) new TermDistinctValuesCollector(groupField, countField, (Collection) searchGroups);
|
||||
return (DistinctValuesCollector) new TermDistinctValuesCollector(groupField, countField, (Collection) searchGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private <T> AbstractFirstPassGroupingCollector<T> createRandomFirstPassCollector(Sort groupSort, String groupField, int topNGroups) throws IOException {
|
||||
private <T> FirstPassGroupingCollector<T> createRandomFirstPassCollector(Sort groupSort, String groupField, int topNGroups) throws IOException {
|
||||
Random random = random();
|
||||
if (random.nextBoolean()) {
|
||||
return (AbstractFirstPassGroupingCollector<T>) new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new HashMap<>(), groupSort, topNGroups);
|
||||
return (FirstPassGroupingCollector<T>) new FunctionFirstPassGroupingCollector(new BytesRefFieldSource(groupField), new HashMap<>(), groupSort, topNGroups);
|
||||
} else {
|
||||
return (AbstractFirstPassGroupingCollector<T>) new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
|
||||
return (FirstPassGroupingCollector<T>) new TermFirstPassGroupingCollector(groupField, groupSort, topNGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private List<AbstractDistinctValuesCollector.GroupCount<Comparable<?>>> createExpectedResult(IndexContext context, String term, Sort groupSort, int topN) {
|
||||
class GroupCount extends AbstractDistinctValuesCollector.GroupCount<BytesRef> {
|
||||
private List<DistinctValuesCollector.GroupCount<Comparable<?>>> createExpectedResult(IndexContext context, String term, Sort groupSort, int topN) {
|
||||
class GroupCount extends DistinctValuesCollector.GroupCount<BytesRef> {
|
||||
GroupCount(BytesRef groupValue, Collection<BytesRef> uniqueValues) {
|
||||
super(groupValue);
|
||||
this.uniqueValues.addAll(uniqueValues);
|
||||
|
|
|
@ -103,7 +103,7 @@ public class GroupFacetCollectorTest extends AbstractGroupingTestCase {
|
|||
IndexSearcher indexSearcher = newSearcher(w.getReader());
|
||||
|
||||
List<TermGroupFacetCollector.FacetEntry> entries;
|
||||
AbstractGroupFacetCollector groupedAirportFacetCollector;
|
||||
GroupFacetCollector groupedAirportFacetCollector;
|
||||
TermGroupFacetCollector.GroupedFacetResult airportResult;
|
||||
|
||||
for (int limit : new int[] { 2, 10, 100, Integer.MAX_VALUE }) {
|
||||
|
@ -136,7 +136,7 @@ public class GroupFacetCollectorTest extends AbstractGroupingTestCase {
|
|||
assertEquals(1, entries.get(0).getCount());
|
||||
}
|
||||
|
||||
AbstractGroupFacetCollector groupedDurationFacetCollector = createRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "duration_dv" : "duration", null, false);
|
||||
GroupFacetCollector groupedDurationFacetCollector = createRandomCollector(useDv ? "hotel_dv" : "hotel", useDv ? "duration_dv" : "duration", null, false);
|
||||
indexSearcher.search(new MatchAllDocsQuery(), groupedDurationFacetCollector);
|
||||
TermGroupFacetCollector.GroupedFacetResult durationResult = groupedDurationFacetCollector.mergeSegmentResults(10, 0, false);
|
||||
assertEquals(4, durationResult.getTotalCount());
|
||||
|
@ -344,7 +344,7 @@ public class GroupFacetCollectorTest extends AbstractGroupingTestCase {
|
|||
|
||||
w.close();
|
||||
IndexSearcher indexSearcher = newSearcher(DirectoryReader.open(dir));
|
||||
AbstractGroupFacetCollector groupedAirportFacetCollector = createRandomCollector(groupField + "_dv", "airport", null, true);
|
||||
GroupFacetCollector groupedAirportFacetCollector = createRandomCollector(groupField + "_dv", "airport", null, true);
|
||||
indexSearcher.search(new MatchAllDocsQuery(), groupedAirportFacetCollector);
|
||||
TermGroupFacetCollector.GroupedFacetResult airportResult = groupedAirportFacetCollector.mergeSegmentResults(10, 0, false);
|
||||
assertEquals(3, airportResult.getTotalCount());
|
||||
|
@ -404,7 +404,7 @@ public class GroupFacetCollectorTest extends AbstractGroupingTestCase {
|
|||
}
|
||||
|
||||
GroupedFacetResult expectedFacetResult = createExpectedFacetResult(searchTerm, context, offset, limit, minCount, orderByCount, facetPrefix);
|
||||
AbstractGroupFacetCollector groupFacetCollector = createRandomCollector("group", "facet", facetPrefix, multipleFacetsPerDocument);
|
||||
GroupFacetCollector groupFacetCollector = createRandomCollector("group", "facet", facetPrefix, multipleFacetsPerDocument);
|
||||
searcher.search(new TermQuery(new Term("content", searchTerm)), groupFacetCollector);
|
||||
TermGroupFacetCollector.GroupedFacetResult actualFacetResult = groupFacetCollector.mergeSegmentResults(size, minCount, orderByCount);
|
||||
|
||||
|
@ -704,7 +704,7 @@ public class GroupFacetCollectorTest extends AbstractGroupingTestCase {
|
|||
return new GroupedFacetResult(totalCount, totalMissCount, entriesResult);
|
||||
}
|
||||
|
||||
private AbstractGroupFacetCollector createRandomCollector(String groupField, String facetField, String facetPrefix, boolean multipleFacetsPerDocument) {
|
||||
private GroupFacetCollector createRandomCollector(String groupField, String facetField, String facetPrefix, boolean multipleFacetsPerDocument) {
|
||||
BytesRef facetPrefixBR = facetPrefix == null ? null : new BytesRef(facetPrefix);
|
||||
return TermGroupFacetCollector.createTermGroupFacetCollector(groupField, facetField, multipleFacetsPerDocument, facetPrefixBR, random().nextInt(1024));
|
||||
}
|
||||
|
|
|
@ -144,10 +144,10 @@ public class TestGrouping extends LuceneTestCase {
|
|||
|
||||
final Sort groupSort = Sort.RELEVANCE;
|
||||
|
||||
final AbstractFirstPassGroupingCollector<?> c1 = createRandomFirstPassCollector(groupField, groupSort, 10);
|
||||
final FirstPassGroupingCollector<?> c1 = createRandomFirstPassCollector(groupField, groupSort, 10);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), c1);
|
||||
|
||||
final AbstractSecondPassGroupingCollector<?> c2 = createSecondPassCollector(c1, groupField, groupSort, Sort.RELEVANCE, 0, 5, true, true, true);
|
||||
final SecondPassGroupingCollector<?> c2 = createSecondPassCollector(c1, groupField, groupSort, Sort.RELEVANCE, 0, 5, true, true, true);
|
||||
indexSearcher.search(new TermQuery(new Term("content", "random")), c2);
|
||||
|
||||
final TopGroups<?> groups = c2.getTopGroups(0);
|
||||
|
@ -195,8 +195,8 @@ public class TestGrouping extends LuceneTestCase {
|
|||
doc.add(new SortedDocValuesField(groupField, new BytesRef(value)));
|
||||
}
|
||||
|
||||
private AbstractFirstPassGroupingCollector<?> createRandomFirstPassCollector(String groupField, Sort groupSort, int topDocs) throws IOException {
|
||||
AbstractFirstPassGroupingCollector<?> selected;
|
||||
private FirstPassGroupingCollector<?> createRandomFirstPassCollector(String groupField, Sort groupSort, int topDocs) throws IOException {
|
||||
FirstPassGroupingCollector<?> selected;
|
||||
if (random().nextBoolean()) {
|
||||
ValueSource vs = new BytesRefFieldSource(groupField);
|
||||
selected = new FunctionFirstPassGroupingCollector(vs, new HashMap<>(), groupSort, topDocs);
|
||||
|
@ -209,7 +209,7 @@ public class TestGrouping extends LuceneTestCase {
|
|||
return selected;
|
||||
}
|
||||
|
||||
private AbstractFirstPassGroupingCollector<?> createFirstPassCollector(String groupField, Sort groupSort, int topDocs, AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector) throws IOException {
|
||||
private FirstPassGroupingCollector<?> createFirstPassCollector(String groupField, Sort groupSort, int topDocs, FirstPassGroupingCollector<?> firstPassGroupingCollector) throws IOException {
|
||||
if (TermFirstPassGroupingCollector.class.isAssignableFrom(firstPassGroupingCollector.getClass())) {
|
||||
ValueSource vs = new BytesRefFieldSource(groupField);
|
||||
return new FunctionFirstPassGroupingCollector(vs, new HashMap<>(), groupSort, topDocs);
|
||||
|
@ -219,37 +219,37 @@ public class TestGrouping extends LuceneTestCase {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
private <T> AbstractSecondPassGroupingCollector<T> createSecondPassCollector(AbstractFirstPassGroupingCollector firstPassGroupingCollector,
|
||||
String groupField,
|
||||
Sort groupSort,
|
||||
Sort sortWithinGroup,
|
||||
int groupOffset,
|
||||
int maxDocsPerGroup,
|
||||
boolean getScores,
|
||||
boolean getMaxScores,
|
||||
boolean fillSortFields) throws IOException {
|
||||
private <T> SecondPassGroupingCollector<T> createSecondPassCollector(FirstPassGroupingCollector firstPassGroupingCollector,
|
||||
String groupField,
|
||||
Sort groupSort,
|
||||
Sort sortWithinGroup,
|
||||
int groupOffset,
|
||||
int maxDocsPerGroup,
|
||||
boolean getScores,
|
||||
boolean getMaxScores,
|
||||
boolean fillSortFields) throws IOException {
|
||||
|
||||
if (TermFirstPassGroupingCollector.class.isAssignableFrom(firstPassGroupingCollector.getClass())) {
|
||||
Collection<SearchGroup<BytesRef>> searchGroups = firstPassGroupingCollector.getTopGroups(groupOffset, fillSortFields);
|
||||
return (AbstractSecondPassGroupingCollector) new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup , getScores, getMaxScores, fillSortFields);
|
||||
return (SecondPassGroupingCollector) new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup , getScores, getMaxScores, fillSortFields);
|
||||
} else {
|
||||
ValueSource vs = new BytesRefFieldSource(groupField);
|
||||
Collection<SearchGroup<MutableValue>> searchGroups = firstPassGroupingCollector.getTopGroups(groupOffset, fillSortFields);
|
||||
return (AbstractSecondPassGroupingCollector) new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap());
|
||||
return (SecondPassGroupingCollector) new FunctionSecondPassGroupingCollector(searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup, getScores, getMaxScores, fillSortFields, vs, new HashMap());
|
||||
}
|
||||
}
|
||||
|
||||
// Basically converts searchGroups from MutableValue to BytesRef if grouping by ValueSource
|
||||
@SuppressWarnings("unchecked")
|
||||
private AbstractSecondPassGroupingCollector<?> createSecondPassCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
|
||||
String groupField,
|
||||
Collection<SearchGroup<BytesRef>> searchGroups,
|
||||
Sort groupSort,
|
||||
Sort sortWithinGroup,
|
||||
int maxDocsPerGroup,
|
||||
boolean getScores,
|
||||
boolean getMaxScores,
|
||||
boolean fillSortFields) throws IOException {
|
||||
private SecondPassGroupingCollector<?> createSecondPassCollector(FirstPassGroupingCollector<?> firstPassGroupingCollector,
|
||||
String groupField,
|
||||
Collection<SearchGroup<BytesRef>> searchGroups,
|
||||
Sort groupSort,
|
||||
Sort sortWithinGroup,
|
||||
int maxDocsPerGroup,
|
||||
boolean getScores,
|
||||
boolean getMaxScores,
|
||||
boolean fillSortFields) throws IOException {
|
||||
if (firstPassGroupingCollector.getClass().isAssignableFrom(TermFirstPassGroupingCollector.class)) {
|
||||
return new TermSecondPassGroupingCollector(groupField, searchGroups, groupSort, sortWithinGroup, maxDocsPerGroup , getScores, getMaxScores, fillSortFields);
|
||||
} else {
|
||||
|
@ -272,8 +272,8 @@ public class TestGrouping extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private AbstractAllGroupsCollector<?> createAllGroupsCollector(AbstractFirstPassGroupingCollector<?> firstPassGroupingCollector,
|
||||
String groupField) {
|
||||
private AllGroupsCollector<?> createAllGroupsCollector(FirstPassGroupingCollector<?> firstPassGroupingCollector,
|
||||
String groupField) {
|
||||
if (firstPassGroupingCollector.getClass().isAssignableFrom(TermFirstPassGroupingCollector.class)) {
|
||||
return new TermAllGroupsCollector(groupField);
|
||||
} else {
|
||||
|
@ -305,7 +305,7 @@ public class TestGrouping extends LuceneTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private Collection<SearchGroup<BytesRef>> getSearchGroups(AbstractFirstPassGroupingCollector<?> c, int groupOffset, boolean fillFields) throws IOException {
|
||||
private Collection<SearchGroup<BytesRef>> getSearchGroups(FirstPassGroupingCollector<?> c, int groupOffset, boolean fillFields) throws IOException {
|
||||
if (TermFirstPassGroupingCollector.class.isAssignableFrom(c.getClass())) {
|
||||
return ((TermFirstPassGroupingCollector) c).getTopGroups(groupOffset, fillFields);
|
||||
} else if (FunctionFirstPassGroupingCollector.class.isAssignableFrom(c.getClass())) {
|
||||
|
@ -328,7 +328,7 @@ public class TestGrouping extends LuceneTestCase {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private TopGroups<BytesRef> getTopGroups(AbstractSecondPassGroupingCollector c, int withinGroupOffset) {
|
||||
private TopGroups<BytesRef> getTopGroups(SecondPassGroupingCollector c, int withinGroupOffset) {
|
||||
if (c.getClass().isAssignableFrom(TermSecondPassGroupingCollector.class)) {
|
||||
return ((TermSecondPassGroupingCollector) c).getTopGroups(withinGroupOffset);
|
||||
} else if (c.getClass().isAssignableFrom(FunctionSecondPassGroupingCollector.class)) {
|
||||
|
@ -874,11 +874,11 @@ public class TestGrouping extends LuceneTestCase {
|
|||
if (VERBOSE) {
|
||||
System.out.println(" groupField=" + groupField);
|
||||
}
|
||||
final AbstractFirstPassGroupingCollector<?> c1 = createRandomFirstPassCollector(groupField, groupSort, groupOffset+topNGroups);
|
||||
final FirstPassGroupingCollector<?> c1 = createRandomFirstPassCollector(groupField, groupSort, groupOffset+topNGroups);
|
||||
final CachingCollector cCache;
|
||||
final Collector c;
|
||||
|
||||
final AbstractAllGroupsCollector<?> allGroupsCollector;
|
||||
final AllGroupsCollector<?> allGroupsCollector;
|
||||
if (doAllGroups) {
|
||||
allGroupsCollector = createAllGroupsCollector(c1, groupField);
|
||||
} else {
|
||||
|
@ -953,7 +953,7 @@ public class TestGrouping extends LuceneTestCase {
|
|||
|
||||
final TopGroups<BytesRef> topGroupsShards = searchShards(s, shards.subSearchers, query, groupSort, docSort,
|
||||
groupOffset, topNGroups, docOffset, docsPerGroup, getScores, getMaxScores, true, false);
|
||||
final AbstractSecondPassGroupingCollector<?> c2;
|
||||
final SecondPassGroupingCollector<?> c2;
|
||||
if (topGroups != null) {
|
||||
|
||||
if (VERBOSE) {
|
||||
|
@ -1172,8 +1172,8 @@ public class TestGrouping extends LuceneTestCase {
|
|||
// Run 1st pass collector to get top groups per shard
|
||||
final Weight w = topSearcher.createNormalizedWeight(query, getScores);
|
||||
final List<Collection<SearchGroup<BytesRef>>> shardGroups = new ArrayList<>();
|
||||
List<AbstractFirstPassGroupingCollector<?>> firstPassGroupingCollectors = new ArrayList<>();
|
||||
AbstractFirstPassGroupingCollector<?> firstPassCollector = null;
|
||||
List<FirstPassGroupingCollector<?>> firstPassGroupingCollectors = new ArrayList<>();
|
||||
FirstPassGroupingCollector<?> firstPassCollector = null;
|
||||
boolean shardsCanUseIDV = canUseIDV;
|
||||
|
||||
String groupField = "group";
|
||||
|
@ -1223,7 +1223,7 @@ public class TestGrouping extends LuceneTestCase {
|
|||
@SuppressWarnings({"unchecked","rawtypes"})
|
||||
final TopGroups<BytesRef>[] shardTopGroups = new TopGroups[subSearchers.length];
|
||||
for(int shardIDX=0;shardIDX<subSearchers.length;shardIDX++) {
|
||||
final AbstractSecondPassGroupingCollector<?> secondPassCollector = createSecondPassCollector(firstPassGroupingCollectors.get(shardIDX),
|
||||
final SecondPassGroupingCollector<?> secondPassCollector = createSecondPassCollector(firstPassGroupingCollectors.get(shardIDX),
|
||||
groupField, mergedTopGroups, groupSort, docSort, docOffset + topNDocs, getScores, getMaxScores, true);
|
||||
subSearchers[shardIDX].search(w, secondPassCollector);
|
||||
shardTopGroups[shardIDX] = getTopGroups(secondPassCollector, 0);
|
||||
|
|
|
@ -51,7 +51,7 @@ import org.apache.lucene.search.FilterCollector;
|
|||
import org.apache.lucene.search.LeafCollector;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermGroupFacetCollector;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
@ -282,7 +282,7 @@ public class SimpleFacets {
|
|||
} else {
|
||||
return base;
|
||||
}
|
||||
AbstractAllGroupHeadsCollector allGroupHeadsCollector = grouping.getCommands().get(0).createAllGroupCollector();
|
||||
AllGroupHeadsCollector allGroupHeadsCollector = grouping.getCommands().get(0).createAllGroupCollector();
|
||||
searcher.search(base.getTopFilter(), allGroupHeadsCollector);
|
||||
return new BitDocSet(allGroupHeadsCollector.retrieveGroupHeads(searcher.maxDoc()));
|
||||
} else {
|
||||
|
|
|
@ -46,7 +46,7 @@ import org.apache.lucene.search.TopDocsCollector;
|
|||
import org.apache.lucene.search.TopFieldCollector;
|
||||
import org.apache.lucene.search.TopScoreDocCollector;
|
||||
import org.apache.lucene.search.TotalHitCountCollector;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.GroupDocs;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.search.grouping.TopGroups;
|
||||
|
@ -323,7 +323,7 @@ public class Grouping {
|
|||
cmd.prepare();
|
||||
}
|
||||
|
||||
AbstractAllGroupHeadsCollector<?> allGroupHeadsCollector = null;
|
||||
AllGroupHeadsCollector<?> allGroupHeadsCollector = null;
|
||||
List<Collector> collectors = new ArrayList<>(commands.size());
|
||||
for (Command cmd : commands) {
|
||||
Collector collector = cmd.createFirstPassCollector();
|
||||
|
@ -513,7 +513,7 @@ public class Grouping {
|
|||
* Note: Maybe the creating the response structure should be done in something like a ReponseBuilder???
|
||||
* Warning NOT thread save!
|
||||
*/
|
||||
public abstract class Command<GROUP_VALUE_TYPE> {
|
||||
public abstract class Command<T> {
|
||||
|
||||
public String key; // the name to use for this group in the response
|
||||
public Sort withinGroupSort; // the sort of the documents *within* a single group.
|
||||
|
@ -527,7 +527,7 @@ public class Grouping {
|
|||
public boolean main; // use as the main result in simple format (grouped.main=true param)
|
||||
public TotalCount totalCount = TotalCount.ungrouped;
|
||||
|
||||
TopGroups<GROUP_VALUE_TYPE> result;
|
||||
TopGroups<T> result;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -565,7 +565,7 @@ public class Grouping {
|
|||
* @return a collector that is able to return the most relevant document of all groups.
|
||||
* @throws IOException If I/O related errors occur
|
||||
*/
|
||||
public AbstractAllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
public AllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -774,7 +774,7 @@ public class Grouping {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public AbstractAllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
public AllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
Sort sortWithinGroup = withinGroupSort != null ? withinGroupSort : Sort.RELEVANCE;
|
||||
return TermAllGroupHeadsCollector.create(groupBy, sortWithinGroup);
|
||||
}
|
||||
|
@ -992,7 +992,7 @@ public class Grouping {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AbstractAllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
public AllGroupHeadsCollector<?> createAllGroupCollector() throws IOException {
|
||||
Sort sortWithinGroup = withinGroupSort != null ? withinGroupSort : Sort.RELEVANCE;
|
||||
return new FunctionAllGroupHeadsCollector(groupBy, context, sortWithinGroup);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.apache.lucene.search.MultiCollector;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TimeLimitingCollector;
|
||||
import org.apache.lucene.search.TotalHitCountCollector;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionAllGroupHeadsCollector;
|
||||
import org.apache.lucene.search.grouping.term.TermAllGroupHeadsCollector;
|
||||
import org.apache.solr.common.util.NamedList;
|
||||
|
@ -170,7 +170,7 @@ public class CommandHandler {
|
|||
SchemaField sf = searcher.getSchema().getField(field);
|
||||
FieldType fieldType = sf.getType();
|
||||
|
||||
final AbstractAllGroupHeadsCollector allGroupHeadsCollector;
|
||||
final AllGroupHeadsCollector allGroupHeadsCollector;
|
||||
if (fieldType.getNumericType() != null) {
|
||||
ValueSource vs = fieldType.getValueSource(sf, null);
|
||||
allGroupHeadsCollector = new FunctionAllGroupHeadsCollector(vs, new HashMap(), firstCommand.getSortWithinGroup());
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.apache.solr.search.grouping.distributed.command;
|
|||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Collector;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AbstractAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.AbstractFirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.AllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.FirstPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.search.grouping.function.FunctionAllGroupsCollector;
|
||||
import org.apache.lucene.search.grouping.function.FunctionFirstPassGroupingCollector;
|
||||
|
@ -81,8 +81,8 @@ public class SearchGroupsFieldCommand implements Command<SearchGroupsFieldComman
|
|||
private final int topNGroups;
|
||||
private final boolean includeGroupCount;
|
||||
|
||||
private AbstractFirstPassGroupingCollector firstPassGroupingCollector;
|
||||
private AbstractAllGroupsCollector allGroupsCollector;
|
||||
private FirstPassGroupingCollector firstPassGroupingCollector;
|
||||
private AllGroupsCollector allGroupsCollector;
|
||||
|
||||
private SearchGroupsFieldCommand(SchemaField field, Sort groupSort, int topNGroups, boolean includeGroupCount) {
|
||||
this.field = field;
|
||||
|
|
|
@ -19,7 +19,7 @@ package org.apache.solr.search.grouping.distributed.command;
|
|||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Collector;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.apache.lucene.search.grouping.AbstractSecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.SecondPassGroupingCollector;
|
||||
import org.apache.lucene.search.grouping.GroupDocs;
|
||||
import org.apache.lucene.search.grouping.SearchGroup;
|
||||
import org.apache.lucene.search.grouping.TopGroups;
|
||||
|
@ -106,7 +106,7 @@ public class TopGroupsFieldCommand implements Command<TopGroups<BytesRef>> {
|
|||
private final int maxDocPerGroup;
|
||||
private final boolean needScores;
|
||||
private final boolean needMaxScore;
|
||||
private AbstractSecondPassGroupingCollector secondPassCollector;
|
||||
private SecondPassGroupingCollector secondPassCollector;
|
||||
|
||||
private TopGroupsFieldCommand(SchemaField field,
|
||||
Sort groupSort,
|
||||
|
|
Loading…
Reference in New Issue