diff --git a/src/Lucene.Net.Grouping/GroupingSearch.cs b/src/Lucene.Net.Grouping/GroupingSearch.cs
index 96b23a068f..a8a2edd0dd 100644
--- a/src/Lucene.Net.Grouping/GroupingSearch.cs
+++ b/src/Lucene.Net.Grouping/GroupingSearch.cs
@@ -33,270 +33,39 @@ namespace Lucene.Net.Search.Grouping
/// Convenience class to perform grouping in a non distributed environment.
/// @lucene.experimental
///
- public class GroupingSearch
+ public static class GroupingSearch
{
- private readonly string groupField;
- private readonly ValueSource groupFunction;
- private readonly IDictionary /* Map, ?> */ valueSourceContext;
- private readonly Filter groupEndDocs;
-
- private Sort groupSort = Sort.RELEVANCE;
- private Sort sortWithinGroup;
-
- private int groupDocsOffset;
- private int groupDocsLimit = 1;
- private bool fillSortFields;
- private bool includeScores = true;
- private bool includeMaxScore = true;
-
- private double? maxCacheRAMMB;
- private int? maxDocsToCache;
- private bool cacheScores;
- private bool allGroups;
- private bool allGroupHeads;
- private int initialSize = 128;
-
- private ICollection /* Collection> */ matchingGroups;
- private IBits matchingGroupHeads;
-
- ///
- /// Constructs a instance that groups documents by index terms using the .
- /// The group field can only have one token per document. This means that the field must not be analysed.
- ///
- /// The name of the field to group by.
- public GroupingSearch(string groupField)
- : this(groupField, null, null, null)
- {
- }
-
- ///
- /// Constructs a instance that groups documents by function using a
- /// instance.
- ///
- /// The function to group by specified as
- /// The context of the specified groupFunction
- public GroupingSearch(ValueSource groupFunction, IDictionary /* Map, ?> */ valueSourceContext)
- : this(null, groupFunction, valueSourceContext, null)
- {
-
- }
-
- ///
- /// Constructor for grouping documents by doc block.
- /// This constructor can only be used when documents belonging in a group are indexed in one block.
- ///
- /// The filter that marks the last document in all doc blocks
- public GroupingSearch(Filter groupEndDocs)
- : this(null, null, null, groupEndDocs)
- {
- }
-
- private GroupingSearch(string groupField, ValueSource groupFunction, IDictionary /* Map, ?> */ valueSourceContext, Filter groupEndDocs)
- {
- this.groupField = groupField;
- this.groupFunction = groupFunction;
- this.valueSourceContext = valueSourceContext;
- this.groupEndDocs = groupEndDocs;
- }
-
- ///
- /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes discovering the return type easier.
- public virtual ITopGroups Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+ public static FieldGroupingSearch ByField(string groupField)
{
- return Search(searcher, null, query, groupOffset, groupLimit);
+ return new FieldGroupingSearch(groupField);
}
- ///
- /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The filter to execute with the grouping
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes discovering the return type easier.
- public virtual ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
- {
- if (groupFunction != null)
- {
- return GroupByFunction(searcher, filter, query, groupOffset, groupLimit);
- }
- else if (groupField != null)
- {
- return GroupByField(searcher, filter, query, groupOffset, groupLimit);
- }
- else if (groupEndDocs != null)
- {
- return GroupByDocBlock(searcher, filter, query, groupOffset, groupLimit);
- }
- else
- {
- throw IllegalStateException.Create("Either groupField, groupFunction or groupEndDocs must be set."); // This can't happen...
- }
- }
-
- ///
- /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The expected return type of the search.
- /// The instance to execute the grouped search on.
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- public virtual ITopGroups Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
- {
- return Search(searcher, null, query, groupOffset, groupLimit);
- }
-
- ///
- /// Executes a grouped search. Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The expected return type of the search.
- /// The instance to execute the grouped search on.
- /// The filter to execute with the grouping
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- public virtual ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
- {
- if (groupFunction != null)
- {
- //LUCENENET Specific gaurd clause provides diagnostic info when TGroupValue is inappropriate type.
- if (!typeof(TGroupValue).IsSubclassOf(typeof(MutableValue)) && typeof(TGroupValue) != typeof(MutableValue) && typeof(TGroupValue) != typeof(object))
- {
- throw IllegalStateException.Create("Generic closing type specified must be MutableValue, inherit from MutableValue, or be of type object since grouping by function.");
- }
- return (ITopGroups)GroupByFunction(searcher, filter, query, groupOffset, groupLimit);
- }
- else if (groupField != null)
- {
- return GroupByField(searcher, filter, query, groupOffset, groupLimit);
- }
- else if (groupEndDocs != null)
- {
- return GroupByDocBlock(searcher, filter, query, groupOffset, groupLimit);
- }
- else
- {
- throw IllegalStateException.Create("Either groupField, groupFunction or groupEndDocs must be set."); // This can't happen...
- }
- }
-
- ///
- /// Executes a grouped search base on the field specified via the constructor. Both the first pass
- /// and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes searching by field easier due to concrete return type
- public virtual ITopGroups SearchByField(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+ public static FunctionGroupingSearch ByFunction(ValueSource groupFunction, IDictionary valueSourceContext)
+ where TMutableValue : MutableValue
{
- return GroupByField(searcher, null, query, groupOffset, groupLimit);
+ return new FunctionGroupingSearch(groupFunction, valueSourceContext);
}
-
- ///
- /// Executes a grouped search base on the field specified via the constructor. Both the first pass
- /// and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The filter to execute with the grouping
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes searching by field easier due to concrete return type
- public virtual ITopGroups SearchByField(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+ public static DocBlockGroupingSearch ByDocBlock(Filter groupEndDocs)
{
- if (groupField is null)
- {
- throw IllegalStateException.Create("Must use constructor to set pass a non null value for groupField.");
- }
-
- if (groupFunction != null)
- {
- throw IllegalStateException.Create("The groupFunction must be null.");
- }
- return GroupByField(searcher, filter, query, groupOffset, groupLimit);
+ return new DocBlockGroupingSearch(groupEndDocs);
}
+ }
- ///
- /// Executes a grouped search base on the function specified by a passed via the constructor.
- /// Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes searching by function easier due to ability to specify type of MutableValue returned.
- public virtual ITopGroups SearchByFunction(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
- where TMutableValue : MutableValue
- {
- return GroupByFunction(searcher, null, query, groupOffset, groupLimit);
- }
+ public class FieldGroupingSearch : AbstractGroupingSearch
+ {
+ private readonly string groupField;
- ///
- /// Executes a grouped search base on the function specified by a passed via the constructor.
- /// Both the first pass and second pass are executed on the specified searcher.
- ///
- /// The instance to execute the grouped search on.
- /// The filter to execute with the grouping
- /// The query to execute with the grouping
- /// The group offset
- /// The number of groups to return from the specified group offset
- /// the grouped result as a instance
- /// If any I/O related errors occur
- // LUCENENET additional method signature. Makes searching by function easier due to ability to specify type of MutableValue returned.
- public virtual ITopGroups SearchByFunction(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
- where TMutableValue : MutableValue
+ public FieldGroupingSearch(string groupField)
{
- if (groupFunction is null)
- {
- throw IllegalStateException.Create("Either groupField, groupFunction or groupEndDocs must be set."); // This can't happen...
- }
-
- if (groupField != null)
- {
- throw new Exception("The valueSource must be null.");
- }
- return GroupByFunction(searcher, filter, query, groupOffset, groupLimit);
+ this.groupField = groupField;
}
- //LUCENENET: Method replaced by two methods GroupByField and GroupByFunction so that a generic type constraint
- // can be added to the GroupByFunction case.
- //protected virtual ITopGroups GroupByFieldOrFunction(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
- //{
- //}
-
-
- //LUCENENET Specific. One of two methods that replace GroupByFieldOrFunction. Used support SearchByField.
- // This method is essentually a Field specific version of the GroupByFieldOrFunction.
- protected virtual ITopGroups GroupByField(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+ public override ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
{
int topN = groupOffset + groupLimit;
- IAbstractFirstPassGroupingCollector firstPassCollector;
- IAbstractAllGroupsCollector allGroupsCollector;
+ IAbstractFirstPassGroupingCollector firstPassCollector;
+ IAbstractAllGroupsCollector allGroupsCollector;
AbstractAllGroupHeadsCollector allGroupHeadsCollector;
if (groupField is null)
@@ -304,10 +73,10 @@ protected virtual ITopGroups GroupByField(IndexSearche
throw IllegalStateException.Create("groupField must be set via the constructor.");
}
- firstPassCollector = (IAbstractFirstPassGroupingCollector)new TermFirstPassGroupingCollector(groupField, groupSort, topN);
+ firstPassCollector = (IAbstractFirstPassGroupingCollector)new TermFirstPassGroupingCollector(groupField, groupSort, topN);
if (allGroups)
{
- allGroupsCollector = (IAbstractAllGroupsCollector)new TermAllGroupsCollector(groupField, initialSize);
+ allGroupsCollector = (IAbstractAllGroupsCollector)new TermAllGroupsCollector(groupField, initialSize);
}
else
{
@@ -363,11 +132,11 @@ protected virtual ITopGroups GroupByField(IndexSearche
if (allGroups)
{
- matchingGroups = (ICollection)allGroupsCollector.Groups;
+ matchingGroups = (ICollection)allGroupsCollector.Groups;
}
else
{
- matchingGroups = (ICollection)Collections.EmptyList();
+ matchingGroups = Collections.EmptyList();
}
if (allGroupHeads)
{
@@ -378,19 +147,19 @@ protected virtual ITopGroups GroupByField(IndexSearche
matchingGroupHeads = new Bits.MatchNoBits(searcher.IndexReader.MaxDoc);
}
- IEnumerable> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
+ IEnumerable> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
if (topSearchGroups is null)
{
// LUCENENET specific - optimized empty array creation
- return new TopGroups(Array.Empty(), Array.Empty(), 0, 0, Array.Empty>(), float.NaN);
+ return new TopGroups(Array.Empty(), Array.Empty(), 0, 0, Array.Empty>(), float.NaN);
}
int topNInsideGroup = groupDocsOffset + groupDocsLimit;
- IAbstractSecondPassGroupingCollector secondPassCollector;
+ IAbstractSecondPassGroupingCollector secondPassCollector;
secondPassCollector = new TermSecondPassGroupingCollector(groupField, topSearchGroups as IEnumerable>,
groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields)
- as IAbstractSecondPassGroupingCollector;
+ as IAbstractSecondPassGroupingCollector;
if (cachedCollector != null && cachedCollector.IsCached)
{
@@ -403,23 +172,32 @@ protected virtual ITopGroups GroupByField(IndexSearche
if (allGroups)
{
- return new TopGroups(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
+ return new TopGroups(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
}
else
{
return secondPassCollector.GetTopGroups(groupDocsOffset);
}
}
+ }
- //LUCENENET Specific. One of two methods that replace GroupByFieldOrFunction. Used support
- // SearchByFunction in a way that eliminates casting for the caller.
- // This method is essentually a Function specific version of the GroupByFieldOrFunction.
- protected virtual ITopGroups GroupByFunction(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
- where TMutableValue: MutableValue
+ public class FunctionGroupingSearch : AbstractGroupingSearch
+ where T : MutableValue
+ {
+ private readonly ValueSource groupFunction;
+ private readonly IDictionary /* Map, ?> */ valueSourceContext;
+
+ public FunctionGroupingSearch(ValueSource groupFunction, IDictionary /* Map, ?> */ valueSourceContext)
+ {
+ this.groupFunction = groupFunction;
+ this.valueSourceContext = valueSourceContext;
+ }
+
+ public override ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
{
int topN = groupOffset + groupLimit;
- FunctionFirstPassGroupingCollector firstPassCollector;
- FunctionAllGroupsCollector allGroupsCollector;
+ FunctionFirstPassGroupingCollector firstPassCollector;
+ FunctionAllGroupsCollector allGroupsCollector;
AbstractAllGroupHeadsCollector allGroupHeadsCollector;
if (groupFunction is null)
@@ -427,10 +205,10 @@ protected virtual ITopGroups GroupByFunction(Index
throw IllegalStateException.Create("groupFunction must be set via the constructor by specifying a ValueSource.");
}
- firstPassCollector = new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
+ firstPassCollector = new FunctionFirstPassGroupingCollector(groupFunction, valueSourceContext, groupSort, topN);
if (allGroups)
{
- allGroupsCollector = new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
+ allGroupsCollector = new FunctionAllGroupsCollector(groupFunction, valueSourceContext);
}
else
{
@@ -487,11 +265,11 @@ protected virtual ITopGroups GroupByFunction(Index
if (allGroups)
{
- matchingGroups = (ICollection)allGroupsCollector.Groups;
+ matchingGroups = (ICollection)allGroupsCollector.Groups;
}
else
{
- matchingGroups = (ICollection)Collections.EmptyList();
+ matchingGroups = Collections.EmptyList();
}
if (allGroupHeads)
{
@@ -502,19 +280,19 @@ protected virtual ITopGroups GroupByFunction(Index
matchingGroupHeads = new Bits.MatchNoBits(searcher.IndexReader.MaxDoc);
}
- IEnumerable> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
+ IEnumerable> topSearchGroups = firstPassCollector.GetTopGroups(groupOffset, fillSortFields);
if (topSearchGroups is null)
{
// LUCENENET specific - optimized empty array creation
- return new TopGroups(Array.Empty(), Array.Empty(), 0, 0, Array.Empty>(), float.NaN);
+ return new TopGroups(Array.Empty(), Array.Empty(), 0, 0, Array.Empty>(), float.NaN);
}
int topNInsideGroup = groupDocsOffset + groupDocsLimit;
- IAbstractSecondPassGroupingCollector secondPassCollector;
+ IAbstractSecondPassGroupingCollector secondPassCollector;
- secondPassCollector = new FunctionSecondPassGroupingCollector(topSearchGroups as IEnumerable>,
+ secondPassCollector = new FunctionSecondPassGroupingCollector(topSearchGroups as IEnumerable>,
groupSort, sortWithinGroup, topNInsideGroup, includeScores, includeMaxScore, fillSortFields, groupFunction, valueSourceContext)
- as IAbstractSecondPassGroupingCollector;
+ as IAbstractSecondPassGroupingCollector;
if (cachedCollector != null && cachedCollector.IsCached)
@@ -528,23 +306,62 @@ protected virtual ITopGroups GroupByFunction(Index
if (allGroups)
{
- return new TopGroups(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
+ return new TopGroups(secondPassCollector.GetTopGroups(groupDocsOffset), matchingGroups.Count);
}
else
{
return secondPassCollector.GetTopGroups(groupDocsOffset);
}
}
+ }
+
+ public class DocBlockGroupingSearch : AbstractGroupingSearch
+ {
+ private readonly Filter groupEndDocs;
- protected virtual ITopGroups GroupByDocBlock(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
+ public DocBlockGroupingSearch(Filter groupEndDocs)
+ {
+ this.groupEndDocs = groupEndDocs;
+ }
+
+ public override ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit)
{
int topN = groupOffset + groupLimit;
BlockGroupingCollector c = new BlockGroupingCollector(groupSort, topN, includeScores, groupEndDocs);
searcher.Search(query, filter, c);
int topNInsideGroup = groupDocsOffset + groupDocsLimit;
- return c.GetTopGroups(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
+ return c.GetTopGroups(sortWithinGroup, groupOffset, groupDocsOffset, topNInsideGroup, fillSortFields);
+ }
+ }
+
+ public abstract class AbstractGroupingSearch
+ {
+ protected Sort groupSort = Sort.RELEVANCE;
+ protected Sort sortWithinGroup;
+
+ protected int groupDocsOffset;
+ protected int groupDocsLimit = 1;
+ protected bool fillSortFields;
+ protected bool includeScores = true;
+ protected bool includeMaxScore = true;
+
+ protected double? maxCacheRAMMB;
+ protected int? maxDocsToCache;
+ protected bool cacheScores;
+ protected bool allGroups;
+ protected bool allGroupHeads;
+ protected int initialSize = 128;
+
+ protected ICollection matchingGroups;
+ protected IBits matchingGroupHeads;
+
+ public ITopGroups Search(IndexSearcher searcher, Query query, int groupOffset, int groupLimit)
+ {
+ return Search(searcher, null, query, groupOffset, groupLimit);
}
+ public abstract ITopGroups Search(IndexSearcher searcher, Filter filter, Query query, int groupOffset, int groupLimit);
+
///
/// Enables caching for the second pass search. The cache will not grow over a specified limit in MB.
/// The cache is filled during the first pass searched and then replayed during the second pass searched.
@@ -553,7 +370,7 @@ protected virtual ITopGroups GroupByDocBlock(IndexSear
/// The maximum amount in MB the cache is allowed to hold
/// Whether to cache the scores
/// this
- public virtual GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
+ public virtual AbstractGroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheScores)
{
this.maxCacheRAMMB = maxCacheRAMMB;
this.maxDocsToCache = null;
@@ -569,7 +386,7 @@ public virtual GroupingSearch SetCachingInMB(double maxCacheRAMMB, bool cacheSco
/// The maximum number of documents the cache is allowed to hold
/// Whether to cache the scores
/// this
- public virtual GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
+ public virtual AbstractGroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
{
this.maxDocsToCache = maxDocsToCache;
this.maxCacheRAMMB = null;
@@ -581,7 +398,7 @@ public virtual GroupingSearch SetCaching(int maxDocsToCache, bool cacheScores)
/// Disables any enabled cache.
///
/// this
- public virtual GroupingSearch DisableCaching()
+ public virtual AbstractGroupingSearch DisableCaching()
{
this.maxCacheRAMMB = null;
this.maxDocsToCache = null;
@@ -594,7 +411,7 @@ public virtual GroupingSearch DisableCaching()
///
/// The sort for the groups.
/// this
- public virtual GroupingSearch SetGroupSort(Sort groupSort)
+ public virtual AbstractGroupingSearch SetGroupSort(Sort groupSort)
{
this.groupSort = groupSort;
return this;
@@ -606,7 +423,7 @@ public virtual GroupingSearch SetGroupSort(Sort groupSort)
///
/// The sort for documents inside a group
/// this
- public virtual GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
+ public virtual AbstractGroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
{
this.sortWithinGroup = sortWithinGroup;
return this;
@@ -617,7 +434,7 @@ public virtual GroupingSearch SetSortWithinGroup(Sort sortWithinGroup)
///
/// The offset for documents inside a
/// this
- public virtual GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
+ public virtual AbstractGroupingSearch SetGroupDocsOffset(int groupDocsOffset)
{
this.groupDocsOffset = groupDocsOffset;
return this;
@@ -628,7 +445,7 @@ public virtual GroupingSearch SetGroupDocsOffset(int groupDocsOffset)
///
/// The number of documents to return inside a group
/// this
- public virtual GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
+ public virtual AbstractGroupingSearch SetGroupDocsLimit(int groupDocsLimit)
{
this.groupDocsLimit = groupDocsLimit;
return this;
@@ -639,7 +456,7 @@ public virtual GroupingSearch SetGroupDocsLimit(int groupDocsLimit)
///
/// Whether to also fill the sort fields per returned group and groups docs
/// this
- public virtual GroupingSearch SetFillSortFields(bool fillSortFields)
+ public virtual AbstractGroupingSearch SetFillSortFields(bool fillSortFields)
{
this.fillSortFields = fillSortFields;
return this;
@@ -650,7 +467,7 @@ public virtual GroupingSearch SetFillSortFields(bool fillSortFields)
///
/// Whether to include the scores per doc inside a group
/// this
- public virtual GroupingSearch SetIncludeScores(bool includeScores)
+ public virtual AbstractGroupingSearch SetIncludeScores(bool includeScores)
{
this.includeScores = includeScores;
return this;
@@ -661,7 +478,7 @@ public virtual GroupingSearch SetIncludeScores(bool includeScores)
///
/// Whether to include the score of the most relevant document per group
/// this
- public virtual GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
+ public virtual AbstractGroupingSearch SetIncludeMaxScore(bool includeMaxScore)
{
this.includeMaxScore = includeMaxScore;
return this;
@@ -677,35 +494,18 @@ public virtual GroupingSearch SetIncludeMaxScore(bool includeMaxScore)
///
/// to also compute all groups matching the query
/// this
- public virtual GroupingSearch SetAllGroups(bool allGroups)
+ public virtual AbstractGroupingSearch SetAllGroups(bool allGroups)
{
this.allGroups = allGroups;
return this;
}
- ///
- /// If was set to true then all matching groups are returned, otherwise
- /// an empty collection is returned.
- ///
- /// The group value type. This can be a or a instance.
- /// If grouping by doc block this the group value is always null .
- /// all matching groups are returned, or an empty collection
- public virtual ICollection GetAllMatchingGroups()
- {
- return (ICollection)matchingGroups;
- }
-
///
/// If was set to true then all matching groups are returned, otherwise
/// an empty collection is returned.
///
/// all matching groups are returned, or an empty collection
- ///
- /// LUCENENET specific used to get the groups if the type is unknown or if the code expects
- /// any type, since
- /// will throw an exception if the return type is incorrect.
- ///
- public virtual ICollection GetAllMatchingGroups()
+ public virtual ICollection GetAllMatchingGroups()
{
return matchingGroups;
}
@@ -718,7 +518,7 @@ public virtual ICollection GetAllMatchingGroups()
///
/// Whether to compute all group heads (most relevant document per group) matching the query
/// this
- public virtual GroupingSearch SetAllGroupHeads(bool allGroupHeads)
+ public virtual AbstractGroupingSearch SetAllGroupHeads(bool allGroupHeads)
{
this.allGroupHeads = allGroupHeads;
return this;
@@ -744,7 +544,7 @@ public virtual IBits GetAllGroupHeads()
///
/// The initial size of some internal used data structures
/// this
- public virtual GroupingSearch SetInitialSize(int initialSize)
+ public virtual AbstractGroupingSearch SetInitialSize(int initialSize)
{
this.initialSize = initialSize;
return this;
diff --git a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
index d5b09c59a8..d05ec6f192 100644
--- a/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
+++ b/src/Lucene.Net.Tests.Grouping/GroupingSearchTest.cs
@@ -112,9 +112,9 @@ public virtual void TestBasic()
w.Dispose();
Sort groupSort = Sort.RELEVANCE;
- GroupingSearch groupingSearch = CreateRandomGroupingSearch(groupField, groupSort, 5, canUseIDV);
+ SearchDelegate groupingSearch = CreateRandomGroupingSearch(groupField, groupSort, 5, canUseIDV);
- ITopGroups groups = groupingSearch.Search(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10);
+ ITopGroups groups = groupingSearch(indexSearcher, (Filter)null, new TermQuery(new Index.Term("content", "random")), 0, 10);
assertEquals(7, groups.TotalHitCount);
assertEquals(7, groups.TotalGroupedHitCount);
@@ -151,8 +151,8 @@ public virtual void TestBasic()
assertEquals(6, group.ScoreDocs[0].Doc);
Filter lastDocInBlock = new CachingWrapperFilter(new QueryWrapperFilter(new TermQuery(new Index.Term("groupend", "x"))));
- groupingSearch = new GroupingSearch(lastDocInBlock);
- groups = groupingSearch.Search(indexSearcher, null, new TermQuery(new Index.Term("content", "random")), 0, 10);
+ groupingSearch = GroupingSearch.ByDocBlock(lastDocInBlock).Search;
+ groups = groupingSearch(indexSearcher, null, new TermQuery(new Index.Term("content", "random")), 0, 10);
assertEquals(7, groups.TotalHitCount);
assertEquals(7, groups.TotalGroupedHitCount);
@@ -207,28 +207,37 @@ private void CompareGroupValue(string expected, IGroupDocs group)
}
}
- private GroupingSearch CreateRandomGroupingSearch(string groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
+ private delegate ITopGroups SearchDelegate(IndexSearcher indexSearcher, Filter filter, Query query, int groupOffset, int groupLimit);
+
+ private SearchDelegate CreateRandomGroupingSearch(string groupField, Sort groupSort, int docsInGroup, bool canUseIDV)
{
- GroupingSearch groupingSearch;
if (Random.nextBoolean())
{
ValueSource vs = new BytesRefFieldSource(groupField);
- groupingSearch = new GroupingSearch(vs, new Hashtable());
+ var groupingSearch = GroupingSearch.ByFunction(vs, new Hashtable());
+ groupingSearch.SetGroupSort(groupSort);
+ groupingSearch.SetGroupDocsLimit(docsInGroup);
+
+ if (Random.nextBoolean())
+ {
+ groupingSearch.SetCachingInMB(4.0, true);
+ }
+
+ return groupingSearch.Search;
}
else
{
- groupingSearch = new GroupingSearch(groupField);
- }
+ var groupingSearch = GroupingSearch.ByField(groupField);
+ groupingSearch.SetGroupSort(groupSort);
+ groupingSearch.SetGroupDocsLimit(docsInGroup);
- groupingSearch.SetGroupSort(groupSort);
- groupingSearch.SetGroupDocsLimit(docsInGroup);
+ if (Random.nextBoolean())
+ {
+ groupingSearch.SetCachingInMB(4.0, true);
+ }
- if (Random.nextBoolean())
- {
- groupingSearch.SetCachingInMB(4.0, true);
+ return groupingSearch.Search;
}
-
- return groupingSearch;
}
[Test]
@@ -247,7 +256,7 @@ public virtual void TestSetAllGroups()
IndexSearcher indexSearcher = NewSearcher(w.GetReader());
w.Dispose();
- GroupingSearch gs = new GroupingSearch("group");
+ var gs = GroupingSearch.ByField("group");
gs.SetAllGroups(true);
ITopGroups groups = gs.Search(indexSearcher, null, new TermQuery(new Index.Term("group", "foo")), 0, 10);
assertEquals(1, groups.TotalHitCount);
diff --git a/src/Lucene.Net.Tests.Grouping/TestGroupingExtra.cs b/src/Lucene.Net.Tests.Grouping/TestGroupingExtra.cs
index 6bd0b9c802..c1126016f6 100644
--- a/src/Lucene.Net.Tests.Grouping/TestGroupingExtra.cs
+++ b/src/Lucene.Net.Tests.Grouping/TestGroupingExtra.cs
@@ -80,7 +80,7 @@ public void GroupingSearchByField_StringSorted_UsingDocValues_Top3Groups_Top4Doc
}
writer.Commit();
- GroupingSearch groupingSearch = new GroupingSearch("carMake");
+ var groupingSearch = GroupingSearch.ByField("carMake");
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(4); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("carMake_dv", SortFieldType.STRING)));
@@ -91,7 +91,7 @@ public void GroupingSearchByField_StringSorted_UsingDocValues_Top3Groups_Top4Doc
IndexReader reader = writer.GetReader(applyAllDeletes: true);
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.SearchByField(searcher, matchAllQuery, groupOffset: 0, groupLimit: 3);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 3);
int? totalGroupCount = topGroups.TotalGroupCount; //null if not computed
@@ -122,7 +122,7 @@ public void GroupingSearchByField_StringSorted_UsingDocValues_Top3Groups_Top4Doc
assertEquals(expectdValue, output);
/* Output:
-
+
Group: Audi
Audi A3 Orange
Audi A3 Green
@@ -165,7 +165,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingFieldCache_Top10Gr
//as a 8 term trie structure by default. But by specifying int.MaxValue as the NumericPrecisionStep
//we force the inverted index to store the value as a single term. This allows us to use it for
//grouping via FieldCache (although it's no longer good for range queries as they will be slow if
- //the range is large).
+ //the range is large).
var int32OneTerm = new FieldType
{
@@ -192,7 +192,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingFieldCache_Top10Gr
writer.Commit();
ValueSource vs = new BytesRefFieldSource("major");
- GroupingSearch groupingSearch = new GroupingSearch(vs, new Hashtable());
+ var groupingSearch = GroupingSearch.ByFunction(vs, new Hashtable());
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(10); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("major", SortFieldType.INT32)));
@@ -201,7 +201,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingFieldCache_Top10Gr
IndexReader reader = writer.GetReader(applyAllDeletes: true);
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.SearchByFunction(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
StringBuilder sb = new StringBuilder();
foreach (GroupDocs groupDocs in topGroups.Groups)
@@ -230,7 +230,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingFieldCache_Top10Gr
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -284,7 +284,7 @@ public void GroupingSearch_ViaField_StringSorted_UsingFieldCache_Top3Groups_Top4
}
writer.Commit();
- GroupingSearch groupingSearch = new GroupingSearch("carMake");
+ var groupingSearch = GroupingSearch.ByField("carMake");
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(4); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("carMake", SortFieldType.STRING)));
@@ -326,7 +326,7 @@ public void GroupingSearch_ViaField_StringSorted_UsingFieldCache_Top3Groups_Top4
assertEquals(expectdValue, output);
/* Output:
-
+
Group: Audi
Audi A3 Orange
Audi A3 Green
@@ -379,7 +379,7 @@ public void GroupingSearch_ViaField_StringSorted_UsingDocValues_Top3Groups_Top4D
}
writer.Commit();
- GroupingSearch groupingSearch = new GroupingSearch("carMake");
+ var groupingSearch = GroupingSearch.ByField("carMake");
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(4); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("carMake_dv", SortFieldType.STRING)));
@@ -421,7 +421,7 @@ public void GroupingSearch_ViaField_StringSorted_UsingDocValues_Top3Groups_Top4D
assertEquals(expectdValue, output);
/* Output:
-
+
Group: Audi
Audi A3 Orange
Audi A3 Green
@@ -464,7 +464,7 @@ public virtual void GroupingSearch_ViaField_Int32Sorted_UsingFieldCache_Top10Gro
//as a 8 term trie structure by default. But by specifying int.MaxValue as the NumericPrecisionStep
//we force the inverted index to store the value as a single term. This allows us to use it for
//grouping via FieldCache (although it's no longer good for range queries as they will be slow if
- //the range is large).
+ //the range is large).
var int32OneTerm = new FieldType
{
@@ -490,7 +490,7 @@ public virtual void GroupingSearch_ViaField_Int32Sorted_UsingFieldCache_Top10Gro
}
writer.Commit();
- GroupingSearch groupingSearch = new GroupingSearch("major");
+ var groupingSearch = GroupingSearch.ByField("major");
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(10); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("major", SortFieldType.INT32)));
@@ -499,7 +499,7 @@ public virtual void GroupingSearch_ViaField_Int32Sorted_UsingFieldCache_Top10Gro
IndexReader reader = writer.GetReader(applyAllDeletes: true);
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
StringBuilder sb = new StringBuilder();
foreach (GroupDocs groupDocs in topGroups.Groups)
@@ -574,7 +574,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingFieldCache_Top10
//as a 8 term trie structure by default. But by specifying int.MaxValue as the NumericPrecisionStep
//we force the inverted index to store the value as a single term. This allows us to use it for
//grouping via FieldCache (although it's no longer good for range queries as they will be slow if
- //the range is large).
+ //the range is large).
var int32OneTerm = new FieldType
{
@@ -601,7 +601,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingFieldCache_Top10
writer.Commit();
ValueSource vs = new BytesRefFieldSource("major");
- GroupingSearch groupingSearch = new GroupingSearch(vs, new Hashtable());
+ var groupingSearch = GroupingSearch.ByFunction(vs, new Hashtable());
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(10); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("major", SortFieldType.INT32)));
@@ -610,7 +610,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingFieldCache_Top10
IndexReader reader = writer.GetReader(applyAllDeletes: true);
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
StringBuilder sb = new StringBuilder();
foreach (GroupDocs groupDocs in topGroups.Groups)
@@ -639,7 +639,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingFieldCache_Top10
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -696,7 +696,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingDocValues_Top10Gro
writer.Commit();
ValueSource vs = new Int32FieldSource("major");
- GroupingSearch groupingSearch = new GroupingSearch(vs, new Hashtable());
+ var groupingSearch = GroupingSearch.ByFunction(vs, new Hashtable());
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(10); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("major", SortFieldType.INT32)));
@@ -706,7 +706,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingDocValues_Top10Gro
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.SearchByFunction(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 10);
StringBuilder sb = new StringBuilder();
foreach (GroupDocs groupDocs in topGroups.Groups)
@@ -734,7 +734,7 @@ public virtual void GroupingSearchByFunction_Int32Sorted_UsingDocValues_Top10Gro
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -790,7 +790,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingDocValues_Top4Gr
writer.Commit();
ValueSource vs = new Int32FieldSource("major");
- GroupingSearch groupingSearch = new GroupingSearch(vs, new Hashtable());
+ var groupingSearch = GroupingSearch.ByFunction(vs, new Hashtable());
groupingSearch.SetAllGroups(true); //true = compute all groups matching the query
groupingSearch.SetGroupDocsLimit(2); //max docs returned in a group
groupingSearch.SetGroupSort(new Sort(new SortField("major", SortFieldType.INT32)));
@@ -800,7 +800,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingDocValues_Top4Gr
IndexSearcher searcher = new IndexSearcher(reader);
Query matchAllQuery = new MatchAllDocsQuery();
- ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 4);
+ ITopGroups topGroups = groupingSearch.Search(searcher, matchAllQuery, groupOffset: 0, groupLimit: 4);
StringBuilder sb = new StringBuilder();
foreach (GroupDocs groupDocs in topGroups.Groups)
@@ -828,7 +828,7 @@ public virtual void GroupingSearch_ViaFunction_Int32Sorted_UsingDocValues_Top4Gr
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -852,7 +852,7 @@ 4000 4011 10
/// LUCENENET: Additional Unit Test. Low Level test that does not use GroupingSearch
/// Class. Tests grouping by an StringField via the
/// 2 pass by field name approach. Uses DocValues, not FieldCache.
- /// Demonstrates grouping returning ITopGroups
+ /// Demonstrates grouping returning ITopGroups
///
[Test]
[LuceneNetSpecific]
@@ -939,7 +939,7 @@ public virtual void Group_LowLevelNoCaching_ViaField_StringStored_UsingDocValues
assertEquals(expectdValue, output);
/* Output:
-
+
Group: Audi
Audi A3 Orange
Audi A3 Green
@@ -982,7 +982,7 @@ public virtual void Group_LowLevelNoCaching_ViaField_Int32Sorted_UsingFieldCache
//Normally we can not group on a Int32Field because it's stored as a 8 term trie structure
//by default. But by specifying int.MaxValue as the NumericPrecisionStep we force the inverted
//index to store the value as a single term. This allows us to use it for grouping (although
- //it's no longer good for range queries as they will be slow if the range is large).
+ //it's no longer good for range queries as they will be slow if the range is large).
var int32OneTerm = new FieldType
{
@@ -1065,7 +1065,7 @@ public virtual void Group_LowLevelNoCaching_ViaField_Int32Sorted_UsingFieldCache
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -1105,7 +1105,7 @@ public virtual void Group_LowLevelNoCaching_ViaFunction_Int32Sorted_UsingFieldCa
//Normally we can not group on a Int32Field because it's stored as a 8 term trie structure
//by default. But by specifying int.MaxValue as the NumericPrecisionStep we force the inverted
//index to store the value as a single term. This allows us to use it for grouping (although
- //it's no longer good for range queries as they will be slow if the range is large).
+ //it's no longer good for range queries as they will be slow if the range is large).
var int32OneTerm = new FieldType
{
@@ -1192,7 +1192,7 @@ public virtual void Group_LowLevelNoCaching_ViaFunction_Int32Sorted_UsingFieldCa
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45
@@ -1216,7 +1216,7 @@ 4000 4011 10
/// LUCENENET: Additional Unit Test. Low Level test that does not use GroupingSearch
/// Class. Tests grouping by an Int32 via the
/// 2 pass by fuction/valueSource approach. Uses DocValues, not FieldCache.
- /// Demonstrates grouping returning ITopGroups
+ /// Demonstrates grouping returning ITopGroups
///
[Test]
[LuceneNetSpecific]
@@ -1305,7 +1305,7 @@ public virtual void Group_LowLevelNoCaching_ViaFunction_Int32Sorted_UsingDocValu
assertEquals(expectdValue, output);
/* Output:
- *
+ *
Group: 1000
1000 1102 21
1000 1123 45