/// <summary> /// Returns grouped facet results that were computed over zero or more segments. /// Grouped facet counts are merged from zero or more segment results. /// </summary> /// <param name="size">The total number of facets to include. This is typically offset + limit</param> /// <param name="minCount">The minimum count a facet entry should have to be included in the grouped facet result</param> /// <param name="orderByCount"> /// Whether to sort the facet entries by facet entry count. If <c>false</c> then the facets /// are sorted lexicographically in ascending order. /// </param> /// <returns>grouped facet results</returns> /// <exception cref="System.IO.IOException">If I/O related errors occur during merging segment grouped facet counts.</exception> public virtual GroupedFacetResult MergeSegmentResults(int size, int minCount, bool orderByCount) { if (m_segmentFacetCounts != null) { m_segmentResults.Add(CreateSegmentResult()); m_segmentFacetCounts = null; // reset } int totalCount = 0; int missingCount = 0; SegmentResultPriorityQueue segments = new SegmentResultPriorityQueue(m_segmentResults.Count); foreach (AbstractSegmentResult segmentResult in m_segmentResults) { missingCount += segmentResult.m_missing; if (segmentResult.m_mergePos >= segmentResult.m_maxTermPos) { continue; } totalCount += segmentResult.m_total; segments.Add(segmentResult); } GroupedFacetResult facetResult = new GroupedFacetResult(size, minCount, orderByCount, totalCount, missingCount); while (segments.Count > 0) { AbstractSegmentResult segmentResult = segments.Top; BytesRef currentFacetValue = BytesRef.DeepCopyOf(segmentResult.m_mergeTerm); int count = 0; do { count += segmentResult.m_counts[segmentResult.m_mergePos++]; if (segmentResult.m_mergePos < segmentResult.m_maxTermPos) { segmentResult.NextTerm(); segmentResult = segments.UpdateTop(); } else { segments.Pop(); segmentResult = segments.Top; if (segmentResult == null) { break; } } } while (currentFacetValue.Equals(segmentResult.m_mergeTerm)); facetResult.AddFacetCount(currentFacetValue, count); } return(facetResult); }
public void TestRandom() { Random random = Random; int numberOfRuns = TestUtil.NextInt32(random, 3, 6); for (int indexIter = 0; indexIter < numberOfRuns; indexIter++) { bool multipleFacetsPerDocument = random.nextBoolean(); IndexContext context = CreateIndexContext(multipleFacetsPerDocument); IndexSearcher searcher = NewSearcher(context.indexReader); if (Verbose) { Console.WriteLine("TEST: searcher=" + searcher); } for (int searchIter = 0; searchIter < 100; searchIter++) { if (Verbose) { Console.WriteLine("TEST: searchIter=" + searchIter); } bool useDv = !multipleFacetsPerDocument && context.useDV && random.nextBoolean(); string searchTerm = context.contentStrings[random.nextInt(context.contentStrings.Length)]; int limit = random.nextInt(context.facetValues.size()); int offset = random.nextInt(context.facetValues.size() - limit); int size = offset + limit; int minCount = random.nextBoolean() ? 0 : random.nextInt(1 + context.facetWithMostGroups / 10); bool orderByCount = random.nextBoolean(); string randomStr = GetFromSet(context.facetValues, random.nextInt(context.facetValues.size())); string facetPrefix; if (randomStr == null) { facetPrefix = null; } else { int codePointLen = randomStr.CodePointCount(0, randomStr.Length); int randomLen = random.nextInt(codePointLen); if (codePointLen == randomLen - 1) { facetPrefix = null; } else { int end = randomStr.OffsetByCodePoints(0, randomLen); facetPrefix = random.nextBoolean() ? null : randomStr.Substring(end); } } GroupedFacetResult expectedFacetResult = CreateExpectedFacetResult(searchTerm, context, offset, limit, minCount, orderByCount, facetPrefix); AbstractGroupFacetCollector groupFacetCollector = CreateRandomCollector(useDv ? "group_dv" : "group", useDv ? "facet_dv" : "facet", facetPrefix, multipleFacetsPerDocument); searcher.Search(new TermQuery(new Term("content", searchTerm)), groupFacetCollector); TermGroupFacetCollector.GroupedFacetResult actualFacetResult = groupFacetCollector.MergeSegmentResults(size, minCount, orderByCount); IList <TermGroupFacetCollector.FacetEntry> expectedFacetEntries = expectedFacetResult.GetFacetEntries(); IList <TermGroupFacetCollector.FacetEntry> actualFacetEntries = actualFacetResult.GetFacetEntries(offset, limit); if (Verbose) { Console.WriteLine("Use DV: " + useDv); Console.WriteLine("Collector: " + groupFacetCollector.GetType().Name); Console.WriteLine("Num group: " + context.numGroups); Console.WriteLine("Num doc: " + context.numDocs); Console.WriteLine("Index iter: " + indexIter); Console.WriteLine("multipleFacetsPerDocument: " + multipleFacetsPerDocument); Console.WriteLine("Search iter: " + searchIter); Console.WriteLine("Search term: " + searchTerm); Console.WriteLine("Min count: " + minCount); Console.WriteLine("Facet offset: " + offset); Console.WriteLine("Facet limit: " + limit); Console.WriteLine("Facet prefix: " + facetPrefix); Console.WriteLine("Order by count: " + orderByCount); Console.WriteLine("\n=== Expected: \n"); Console.WriteLine("Total count " + expectedFacetResult.TotalCount); Console.WriteLine("Total missing count " + expectedFacetResult.TotalMissingCount); int counter = 0; foreach (TermGroupFacetCollector.FacetEntry expectedFacetEntry in expectedFacetEntries) { Console.WriteLine( string.Format(CultureInfo.InvariantCulture, "{0}. Expected facet value {1} with count {2}", counter++, expectedFacetEntry.Value.Utf8ToString(), expectedFacetEntry.Count ) ); } Console.WriteLine("\n=== Actual: \n"); Console.WriteLine("Total count " + actualFacetResult.TotalCount); Console.WriteLine("Total missing count " + actualFacetResult.TotalMissingCount); counter = 0; foreach (TermGroupFacetCollector.FacetEntry actualFacetEntry in actualFacetEntries) { Console.WriteLine( string.Format(CultureInfo.InvariantCulture, "{0}. Actual facet value {1} with count {2}", counter++, actualFacetEntry.Value.Utf8ToString(), actualFacetEntry.Count ) ); } Console.WriteLine("\n==================================================================================="); } assertEquals(expectedFacetResult.TotalCount, actualFacetResult.TotalCount); assertEquals(expectedFacetResult.TotalMissingCount, actualFacetResult.TotalMissingCount); assertEquals(expectedFacetEntries.size(), actualFacetEntries.size()); for (int i = 0; i < expectedFacetEntries.size(); i++) { TermGroupFacetCollector.FacetEntry expectedFacetEntry = expectedFacetEntries[i]; TermGroupFacetCollector.FacetEntry actualFacetEntry = actualFacetEntries[i]; assertEquals("i=" + i + ": " + expectedFacetEntry.Value.Utf8ToString() + " != " + actualFacetEntry.Value.Utf8ToString(), expectedFacetEntry.Value, actualFacetEntry.Value); assertEquals("i=" + i + ": " + expectedFacetEntry.Count + " != " + actualFacetEntry.Count, expectedFacetEntry.Count, actualFacetEntry.Count); } } context.indexReader.Dispose(); context.dir.Dispose(); } }