You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2013/07/29 15:07:31 UTC
svn commit: r1508043 [1/2] - in /lucene/dev/trunk/lucene: ./
demo/src/java/org/apache/lucene/demo/facet/
facet/src/java/org/apache/lucene/facet/associations/
facet/src/java/org/apache/lucene/facet/params/
facet/src/java/org/apache/lucene/facet/range/ f...
Author: shaie
Date: Mon Jul 29 13:07:30 2013
New Revision: 1508043
URL: http://svn.apache.org/r1508043
Log:
LUCENE-4985: Make it easier to mix different kinds of FacetRequests
Added:
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java
- copied, changed from r1508041, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationFloatSumFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java
- copied, changed from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationIntSumFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java
- copied, changed from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetsAccumulatorWrapper.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java
- copied, changed from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/MultiAssociationsFacetsAggregator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java
- copied, changed from r1507698, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java
Removed:
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationFloatSumFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationIntSumFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/MultiAssociationsFacetsAggregator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetsAccumulatorWrapper.java
Modified:
lucene/dev/trunk/lucene/CHANGES.txt
lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/AssociationsFacetsExample.java
lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java
lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/SimpleSortedSetFacetsExample.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java
lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/associations/AssociationsFacetRequestTest.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/range/TestRangeAccumulator.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/CountingFacetsAggregatorTest.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/FacetResultTest.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestDrillSideways.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java
lucene/dev/trunk/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java
Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Mon Jul 29 13:07:30 2013
@@ -70,6 +70,13 @@ New features
* LUCENE-5091: SpanNotQuery can now be configured with pre and post slop to act
as a hypothetical SpanNotNearQuery. (Tim Allison via David Smiley)
+* LUCENE-4985: FacetsAccumulator.create() is now able to create a
+ MultiFacetsAccumulator over a mixed set of facet requests. MultiFacetsAccumulator
+ allows wrapping multiple FacetsAccumulators, allowing to easily mix
+ existing and custom ones. TaxonomyFacetsAccumulator supports any
+ FacetRequest which implements createFacetsAggregator and was indexed
+ using the taxonomy index. (Shai Erera)
+
Bug Fixes
* LUCENE-5116: IndexWriter.addIndexes(IndexReader...) should drop empty (or all
Modified: lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/AssociationsFacetsExample.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/AssociationsFacetsExample.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/AssociationsFacetsExample.java (original)
+++ lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/AssociationsFacetsExample.java Mon Jul 29 13:07:30 2013
@@ -1,27 +1,20 @@
package org.apache.lucene.demo.facet;
import java.io.IOException;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
-import org.apache.lucene.facet.associations.AssociationFloatSumFacetRequest;
-import org.apache.lucene.facet.associations.AssociationIntSumFacetRequest;
import org.apache.lucene.facet.associations.AssociationsFacetFields;
import org.apache.lucene.facet.associations.CategoryAssociation;
import org.apache.lucene.facet.associations.CategoryAssociationsContainer;
import org.apache.lucene.facet.associations.CategoryFloatAssociation;
import org.apache.lucene.facet.associations.CategoryIntAssociation;
-import org.apache.lucene.facet.associations.MultiAssociationsFacetsAggregator;
-import org.apache.lucene.facet.associations.SumFloatAssociationFacetsAggregator;
-import org.apache.lucene.facet.associations.SumIntAssociationFacetsAggregator;
+import org.apache.lucene.facet.associations.SumFloatAssociationFacetRequest;
+import org.apache.lucene.facet.associations.SumIntAssociationFacetRequest;
import org.apache.lucene.facet.index.FacetFields;
import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.FacetResult;
-import org.apache.lucene.facet.search.FacetsAccumulator;
-import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.FacetsCollector;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -135,22 +128,9 @@ public class AssociationsFacetsExample {
CategoryPath tags = new CategoryPath("tags");
CategoryPath genre = new CategoryPath("genre");
- FacetSearchParams fsp = new FacetSearchParams(
- new AssociationIntSumFacetRequest(tags, 10),
- new AssociationFloatSumFacetRequest(genre, 10));
-
- // every category has a different type of association, so use chain their
- // respective aggregators.
- final Map<CategoryPath,FacetsAggregator> aggregators = new HashMap<CategoryPath,FacetsAggregator>();
- aggregators.put(tags, new SumIntAssociationFacetsAggregator());
- aggregators.put(genre, new SumFloatAssociationFacetsAggregator());
- FacetsAccumulator fa = new FacetsAccumulator(fsp, indexReader, taxoReader) {
- @Override
- public FacetsAggregator getAggregator() {
- return new MultiAssociationsFacetsAggregator(aggregators);
- }
- };
- FacetsCollector fc = FacetsCollector.create(fa);
+ FacetSearchParams fsp = new FacetSearchParams(new SumIntAssociationFacetRequest(tags, 10),
+ new SumFloatAssociationFacetRequest(genre, 10));
+ FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader);
// MatchAllDocsQuery is for "browsing" (counts facets
// for all non-deleted docs in the index); normally
Modified: lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java (original)
+++ lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/RangeFacetsExample.java Mon Jul 29 13:07:30 2013
@@ -27,7 +27,6 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.facet.params.FacetIndexingParams;
-import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.range.LongRange;
import org.apache.lucene.facet.range.RangeAccumulator;
import org.apache.lucene.facet.range.RangeFacetRequest;
@@ -80,13 +79,12 @@ public class RangeFacetsExample implemen
/** User runs a query and counts facets. */
public List<FacetResult> search() throws IOException {
- FacetSearchParams fsp = new FacetSearchParams(
- new RangeFacetRequest<LongRange>("timestamp",
- new LongRange("Past hour", nowSec-3600, true, nowSec, true),
- new LongRange("Past six hours", nowSec-6*3600, true, nowSec, true),
- new LongRange("Past day", nowSec-24*3600, true, nowSec, true)));
+ RangeFacetRequest<LongRange> rangeFacetRequest = new RangeFacetRequest<LongRange>("timestamp",
+ new LongRange("Past hour", nowSec-3600, true, nowSec, true),
+ new LongRange("Past six hours", nowSec-6*3600, true, nowSec, true),
+ new LongRange("Past day", nowSec-24*3600, true, nowSec, true));
// Aggregatses the facet counts
- FacetsCollector fc = FacetsCollector.create(new RangeAccumulator(fsp, searcher.getIndexReader()));
+ FacetsCollector fc = FacetsCollector.create(new RangeAccumulator(rangeFacetRequest));
// MatchAllDocsQuery is for "browsing" (counts facets
// for all non-deleted docs in the index); normally
@@ -112,6 +110,7 @@ public class RangeFacetsExample implemen
return searcher.search(q, 10);
}
+ @Override
public void close() throws IOException {
searcher.getIndexReader().close();
indexDir.close();
Modified: lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/SimpleSortedSetFacetsExample.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/SimpleSortedSetFacetsExample.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/SimpleSortedSetFacetsExample.java (original)
+++ lucene/dev/trunk/lucene/demo/src/java/org/apache/lucene/demo/facet/SimpleSortedSetFacetsExample.java Mon Jul 29 13:07:30 2013
@@ -91,7 +91,7 @@ public class SimpleSortedSetFacetsExampl
new CountFacetRequest(new CategoryPath("Author"), 10));
// Aggregatses the facet counts
- FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(fsp, state));
+ FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(state, fsp));
// MatchAllDocsQuery is for "browsing" (counts facets
// for all non-deleted docs in the index); normally
@@ -117,7 +117,7 @@ public class SimpleSortedSetFacetsExampl
FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("Author"), 10));
DrillDownQuery q = new DrillDownQuery(fsp.indexingParams, new MatchAllDocsQuery());
q.add(new CategoryPath("Publish Year/2010", '/'));
- FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(fsp, state));
+ FacetsCollector fc = FacetsCollector.create(new SortedSetDocValuesAccumulator(state, fsp));
searcher.search(q, fc);
// Retrieve results
Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java (from r1508041, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationFloatSumFacetRequest.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationFloatSumFacetRequest.java&r1=1508041&r2=1508043&rev=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationFloatSumFacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumFloatAssociationFacetRequest.java Mon Jul 29 13:07:30 2013
@@ -1,7 +1,9 @@
package org.apache.lucene.facet.associations;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.search.FacetArrays;
import org.apache.lucene.facet.search.FacetRequest;
+import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.taxonomy.CategoryPath;
/*
@@ -27,17 +29,22 @@ import org.apache.lucene.facet.taxonomy.
*
* @lucene.experimental
*/
-public class AssociationFloatSumFacetRequest extends FacetRequest {
+public class SumFloatAssociationFacetRequest extends FacetRequest {
/**
* Create a float association facet request for a given node in the
* taxonomy.
*/
- public AssociationFloatSumFacetRequest(CategoryPath path, int num) {
+ public SumFloatAssociationFacetRequest(CategoryPath path, int num) {
super(path, num);
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return new SumFloatAssociationFacetsAggregator();
+ }
+
+ @Override
public double getValueOf(FacetArrays arrays, int ordinal) {
return arrays.getFloatArray()[ordinal];
}
Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java (from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationIntSumFacetRequest.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationIntSumFacetRequest.java&r1=1507930&r2=1508043&rev=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/AssociationIntSumFacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/SumIntAssociationFacetRequest.java Mon Jul 29 13:07:30 2013
@@ -1,7 +1,9 @@
package org.apache.lucene.facet.associations;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.search.FacetArrays;
import org.apache.lucene.facet.search.FacetRequest;
+import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.taxonomy.CategoryPath;
/*
@@ -27,17 +29,22 @@ import org.apache.lucene.facet.taxonomy.
*
* @lucene.experimental
*/
-public class AssociationIntSumFacetRequest extends FacetRequest {
+public class SumIntAssociationFacetRequest extends FacetRequest {
/**
* Create an integer association facet request for a given node in the
* taxonomy.
*/
- public AssociationIntSumFacetRequest(CategoryPath path, int num) {
+ public SumIntAssociationFacetRequest(CategoryPath path, int num) {
super(path, num);
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return new SumIntAssociationFacetsAggregator();
+ }
+
+ @Override
public FacetArraysSource getFacetArraysSource() {
return FacetArraysSource.INT;
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/params/FacetSearchParams.java Mon Jul 29 13:07:30 2013
@@ -23,13 +23,9 @@ import org.apache.lucene.facet.search.Fa
*/
/**
- * Defines parameters that are needed for faceted search. The list of
- * {@link FacetRequest facet requests} denotes the facets for which aggregated
- * should be done.
- * <p>
- * One can pass {@link FacetIndexingParams} in order to tell the search code how
- * to read the facets information. Note that you must use the same
- * {@link FacetIndexingParams} that were used for indexing.
+ * Defines parameters that are needed for faceted search: the list of facet
+ * {@link FacetRequest facet requests} which should be aggregated as well as the
+ * {@link FacetIndexingParams indexing params} that were used to index them.
*
* @lucene.experimental
*/
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java Mon Jul 29 13:07:30 2013
@@ -19,6 +19,7 @@ package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.lucene.facet.params.FacetSearchParams;
@@ -26,10 +27,8 @@ import org.apache.lucene.facet.search.Fa
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsAccumulator;
-import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
import org.apache.lucene.facet.taxonomy.CategoryPath;
-import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.NumericDocValues;
/** Uses a {@link NumericDocValues} and accumulates
@@ -51,38 +50,34 @@ public class RangeAccumulator extends Fa
final List<RangeSet> requests = new ArrayList<RangeSet>();
- public RangeAccumulator(FacetSearchParams fsp, IndexReader reader) {
- super(fsp, reader, null, null);
-
- for(FacetRequest fr : fsp.facetRequests) {
-
+ public RangeAccumulator(FacetRequest... facetRequests) {
+ this(Arrays.asList(facetRequests));
+ }
+
+ public RangeAccumulator(List<FacetRequest> facetRequests) {
+ super(new FacetSearchParams(facetRequests));
+ for (FacetRequest fr : facetRequests) {
if (!(fr instanceof RangeFacetRequest)) {
- throw new IllegalArgumentException("only RangeFacetRequest is supported; got " + fsp.facetRequests.get(0).getClass());
+ throw new IllegalArgumentException("this accumulator only supports RangeFacetRequest; got " + fr);
}
if (fr.categoryPath.length != 1) {
throw new IllegalArgumentException("only flat (dimension only) CategoryPath is allowed");
}
-
+
RangeFacetRequest<?> rfr = (RangeFacetRequest<?>) fr;
-
- requests.add(new RangeSet(rfr.ranges, rfr.categoryPath.components[0]));
+ requests.add(new RangeSet(rfr.ranges, fr.categoryPath.components[0]));
}
}
@Override
- public FacetsAggregator getAggregator() {
- throw new UnsupportedOperationException();
- }
-
- @Override
public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {
// TODO: test if this is faster (in the past it was
// faster to do MachingDocs on the inside) ... see
// patches on LUCENE-4965):
List<FacetResult> results = new ArrayList<FacetResult>();
- for(int i=0;i<requests.size();i++) {
+ for (int i = 0; i < requests.size(); i++) {
RangeSet ranges = requests.get(i);
int[] counts = new int[ranges.ranges.length];
@@ -100,7 +95,7 @@ public class RangeAccumulator extends Fa
// (really, a specialized case of the interval
// tree)
// TODO: use interval tree instead of linear search:
- for(int j=0;j<ranges.ranges.length;j++) {
+ for (int j = 0; j < ranges.ranges.length; j++) {
if (ranges.ranges[j].accept(v)) {
counts[j]++;
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java Mon Jul 29 13:07:30 2013
@@ -19,9 +19,11 @@ package org.apache.lucene.facet.range;
import java.util.List;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.search.Aggregator;
import org.apache.lucene.facet.search.FacetArrays;
import org.apache.lucene.facet.search.FacetRequest;
+import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -53,6 +55,11 @@ public class RangeFacetRequest<T extends
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return null;
+ }
+
+ @Override
public double getValueOf(FacetArrays arrays, int ordinal) {
throw new UnsupportedOperationException();
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sampling/Sampler.java Mon Jul 29 13:07:30 2013
@@ -4,12 +4,14 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.Aggregator;
import org.apache.lucene.facet.search.FacetArrays;
import org.apache.lucene.facet.search.FacetRequest;
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetResultNode;
+import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.ScoredDocIDs;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -215,6 +217,11 @@ public abstract class Sampler {
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return orig.createFacetsAggregator(fip);
+ }
+
+ @Override
public Aggregator createAggregator(boolean useComplements, FacetArrays arrays, TaxonomyReader taxonomy)
throws IOException {
return orig.createAggregator(useComplements, arrays, taxonomy);
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountFacetRequest.java Mon Jul 29 13:07:30 2013
@@ -1,6 +1,7 @@
package org.apache.lucene.facet.search;
import org.apache.lucene.facet.complements.ComplementCountingAggregator;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -32,6 +33,7 @@ public class CountFacetRequest extends F
super(path, num);
}
+ // TODO nuke Aggregator and move this logic to StandardFacetsAccumulator -- it should only be used for counting
@Override
public Aggregator createAggregator(boolean useComplements, FacetArrays arrays, TaxonomyReader taxonomy) {
// we rely on that, if needed, result is cleared by arrays!
@@ -43,6 +45,11 @@ public class CountFacetRequest extends F
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return CountingFacetsAggregator.create(fip.getCategoryListParams(categoryPath));
+ }
+
+ @Override
public double getValueOf(FacetArrays arrays, int ordinal) {
return arrays.getIntArray()[ordinal];
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsAggregator.java Mon Jul 29 13:07:30 2013
@@ -2,6 +2,7 @@ package org.apache.lucene.facet.search;
import java.io.IOException;
+import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder;
import org.apache.lucene.facet.params.CategoryListParams;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
import org.apache.lucene.util.IntsRef;
@@ -34,6 +35,18 @@ import org.apache.lucene.util.IntsRef;
*/
public class CountingFacetsAggregator extends IntRollupFacetsAggregator {
+ /**
+ * Returns a {@link FacetsAggregator} suitable for counting categories given
+ * the {@link CategoryListParams}.
+ */
+ public static FacetsAggregator create(CategoryListParams clp) {
+ if (clp.createEncoder().createMatchingDecoder().getClass() == DGapVInt8IntDecoder.class) {
+ return new FastCountingFacetsAggregator();
+ } else {
+ return new CountingFacetsAggregator();
+ }
+ }
+
private final IntsRef ordinals = new IntsRef(32);
@Override
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSideways.java Mon Jul 29 13:07:30 2013
@@ -25,7 +25,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.lucene.facet.index.FacetFields;
import org.apache.lucene.facet.params.FacetSearchParams;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesFacetFields;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
@@ -70,11 +73,26 @@ public class DrillSideways {
protected final IndexSearcher searcher;
protected final TaxonomyReader taxoReader;
-
- /** Create a new {@code DrillSideways} instance. */
+ protected final SortedSetDocValuesReaderState state;
+
+ /**
+ * Create a new {@code DrillSideways} instance, assuming the categories were
+ * indexed with {@link FacetFields}.
+ */
public DrillSideways(IndexSearcher searcher, TaxonomyReader taxoReader) {
this.searcher = searcher;
this.taxoReader = taxoReader;
+ this.state = null;
+ }
+
+ /**
+ * Create a new {@code DrillSideways} instance, assuming the categories were
+ * indexed with {@link SortedSetDocValuesFacetFields}.
+ */
+ public DrillSideways(IndexSearcher searcher, SortedSetDocValuesReaderState state) {
+ this.searcher = searcher;
+ this.taxoReader = null;
+ this.state = state;
}
/** Moves any drill-downs that don't have a corresponding
@@ -440,13 +458,21 @@ public class DrillSideways {
/** Override this to use a custom drill-down {@link
* FacetsAccumulator}. */
protected FacetsAccumulator getDrillDownAccumulator(FacetSearchParams fsp) throws IOException {
- return FacetsAccumulator.create(fsp, searcher.getIndexReader(), taxoReader);
+ if (taxoReader != null) {
+ return FacetsAccumulator.create(fsp, searcher.getIndexReader(), taxoReader, null);
+ } else {
+ return FacetsAccumulator.create(fsp, state, null);
+ }
}
/** Override this to use a custom drill-sideways {@link
* FacetsAccumulator}. */
protected FacetsAccumulator getDrillSidewaysAccumulator(String dim, FacetSearchParams fsp) throws IOException {
- return FacetsAccumulator.create(fsp, searcher.getIndexReader(), taxoReader);
+ if (taxoReader != null) {
+ return FacetsAccumulator.create(fsp, searcher.getIndexReader(), taxoReader, null);
+ } else {
+ return FacetsAccumulator.create(fsp, state, null);
+ }
}
/** Override this and return true if your collector
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetRequest.java Mon Jul 29 13:07:30 2013
@@ -3,6 +3,8 @@ package org.apache.lucene.facet.search;
import java.io.IOException;
import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy;
+import org.apache.lucene.facet.params.FacetIndexingParams;
+import org.apache.lucene.facet.range.RangeFacetRequest;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -139,6 +141,15 @@ public abstract class FacetRequest {
"you should override FacetsAccumulator to return the proper FacetsAggregator");
}
+ /**
+ * Returns the {@link FacetsAggregator} which can aggregate the categories of
+ * this facet request. The aggregator is expected to aggregate category values
+ * into {@link FacetArrays}. If the facet request does not support that, e.g.
+ * {@link RangeFacetRequest}, it can return {@code null}. Note though that
+ * such requests require a dedicated {@link FacetsAccumulator}.
+ */
+ public abstract FacetsAggregator createFacetsAggregator(FacetIndexingParams fip);
+
@Override
public boolean equals(Object o) {
if (o instanceof FacetRequest) {
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetResult.java Mon Jul 29 13:07:30 2013
@@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.util.CollectionUtil;
@@ -153,6 +154,11 @@ public class FacetResult {
}
FacetRequest dummy = new FacetRequest(min, frs.get(0).getFacetRequest().numResults) {
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ throw new UnsupportedOperationException("not supported by this request");
+ }
+
+ @Override
public double getValueOf(FacetArrays arrays, int idx) {
throw new UnsupportedOperationException("not supported by this request");
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java Mon Jul 29 13:07:30 2013
@@ -2,20 +2,15 @@ package org.apache.lucene.facet.search;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder;
-import org.apache.lucene.facet.params.CategoryListParams;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.params.FacetSearchParams;
-import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy;
-import org.apache.lucene.facet.search.FacetRequest.FacetArraysSource;
-import org.apache.lucene.facet.search.FacetRequest.ResultMode;
-import org.apache.lucene.facet.search.FacetRequest.SortOrder;
+import org.apache.lucene.facet.range.RangeAccumulator;
+import org.apache.lucene.facet.range.RangeFacetRequest;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
-import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesAccumulator;
+import org.apache.lucene.facet.sortedset.SortedSetDocValuesReaderState;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.IndexReader;
@@ -37,48 +32,117 @@ import org.apache.lucene.index.IndexRead
*/
/**
- * Driver for Accumulating facets of faceted search requests over given
- * documents.
+ * Accumulates the facets defined in the {@link FacetSearchParams}.
*
* @lucene.experimental
*/
-public class FacetsAccumulator {
+public abstract class FacetsAccumulator {
- public final TaxonomyReader taxonomyReader;
- public final IndexReader indexReader;
- public final FacetArrays facetArrays;
- public FacetSearchParams searchParams;
+ // TODO this should be final, but currently SamplingAccumulator modifies the params.
+ // need to review the class and if it's resolved, make it final
+ public /*final*/ FacetSearchParams searchParams;
+
+ /** Constructor with the given search params. */
+ protected FacetsAccumulator(FacetSearchParams fsp) {
+ this.searchParams = fsp;
+ }
/**
- * Initializes the accumulator with the given search params, index reader and
- * taxonomy reader. This constructor creates the default {@link FacetArrays},
- * which do not support reuse. If you want to use {@link ReusingFacetArrays},
- * you should use the
- * {@link #FacetsAccumulator(FacetSearchParams, IndexReader, TaxonomyReader, FacetArrays)}
- * constructor.
+ * Creates a {@link FacetsAccumulator} for the given facet requests. This
+ * method supports {@link RangeAccumulator} and
+ * {@link TaxonomyFacetsAccumulator} by dividing the facet requests into
+ * {@link RangeFacetRequest} and the rest.
+ * <p>
+ * If both types of facet requests are used, it returns a
+ * {@link MultiFacetsAccumulator} and the facet results returned from
+ * {@link #accumulate(List)} may not be in the same order as the given facet
+ * requests.
+ *
+ * @param fsp
+ * the search params define the facet requests and the
+ * {@link FacetIndexingParams}
+ * @param indexReader
+ * the {@link IndexReader} used for search
+ * @param taxoReader
+ * the {@link TaxonomyReader} used for search
+ * @param arrays
+ * the {@link FacetArrays} which the accumulator should use to store
+ * the categories weights in. Can be {@code null}.
*/
- public FacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
- this(searchParams, indexReader, taxonomyReader, new FacetArrays(taxonomyReader.getSize()));
- }
+ public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader,
+ FacetArrays arrays) {
+ if (fsp.indexingParams.getPartitionSize() != Integer.MAX_VALUE) {
+ return new StandardFacetsAccumulator(fsp, indexReader, taxoReader, arrays);
+ }
+
+ List<FacetRequest> rangeRequests = new ArrayList<FacetRequest>();
+ List<FacetRequest> nonRangeRequests = new ArrayList<FacetRequest>();
+ for (FacetRequest fr : fsp.facetRequests) {
+ if (fr instanceof RangeFacetRequest) {
+ rangeRequests.add(fr);
+ } else {
+ nonRangeRequests.add(fr);
+ }
+ }
+ if (rangeRequests.isEmpty()) {
+ return new TaxonomyFacetsAccumulator(fsp, indexReader, taxoReader, arrays);
+ } else if (nonRangeRequests.isEmpty()) {
+ return new RangeAccumulator(rangeRequests);
+ } else {
+ FacetSearchParams searchParams = new FacetSearchParams(fsp.indexingParams, nonRangeRequests);
+ FacetsAccumulator accumulator = new TaxonomyFacetsAccumulator(searchParams, indexReader, taxoReader, arrays);
+ RangeAccumulator rangeAccumulator = new RangeAccumulator(rangeRequests);
+ return MultiFacetsAccumulator.wrap(accumulator, rangeAccumulator);
+ }
+ }
+
/**
- * Creates an appropriate {@link FacetsAccumulator},
- * returning {@link FacetsAccumulator} when all requests
- * are {@link CountFacetRequest} and only one partition is
- * in use, otherwise {@link StandardFacetsAccumulator}.
+ * Creates a {@link FacetsAccumulator} for the given facet requests. This
+ * method supports {@link RangeAccumulator} and
+ * {@link SortedSetDocValuesAccumulator} by dividing the facet requests into
+ * {@link RangeFacetRequest} and the rest.
+ * <p>
+ * If both types of facet requests are used, it returns a
+ * {@link MultiFacetsAccumulator} and the facet results returned from
+ * {@link #accumulate(List)} may not be in the same order as the given facet
+ * requests.
+ *
+ * @param fsp
+ * the search params define the facet requests and the
+ * {@link FacetIndexingParams}
+ * @param state
+ * the {@link SortedSetDocValuesReaderState} needed for accumulating
+ * the categories
+ * @param arrays
+ * the {@link FacetArrays} which the accumulator should use to
+ * store the categories weights in. Can be {@code null}.
*/
- public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) {
+ public static FacetsAccumulator create(FacetSearchParams fsp, SortedSetDocValuesReaderState state, FacetArrays arrays) throws IOException {
if (fsp.indexingParams.getPartitionSize() != Integer.MAX_VALUE) {
- return new StandardFacetsAccumulator(fsp, indexReader, taxoReader);
+ throw new IllegalArgumentException("only default partition size is supported by this method: " + fsp.indexingParams.getPartitionSize());
}
+ List<FacetRequest> rangeRequests = new ArrayList<FacetRequest>();
+ List<FacetRequest> nonRangeRequests = new ArrayList<FacetRequest>();
for (FacetRequest fr : fsp.facetRequests) {
- if (!(fr instanceof CountFacetRequest)) {
- return new StandardFacetsAccumulator(fsp, indexReader, taxoReader);
+ if (fr instanceof RangeFacetRequest) {
+ rangeRequests.add(fr);
+ } else {
+ nonRangeRequests.add(fr);
}
}
- return new FacetsAccumulator(fsp, indexReader, taxoReader);
+ if (rangeRequests.isEmpty()) {
+ return new SortedSetDocValuesAccumulator(state, fsp, arrays);
+ } else if (nonRangeRequests.isEmpty()) {
+ return new RangeAccumulator(rangeRequests);
+ } else {
+ FacetSearchParams searchParams = new FacetSearchParams(fsp.indexingParams, nonRangeRequests);
+ FacetsAccumulator accumulator = new SortedSetDocValuesAccumulator(state, searchParams, arrays);
+ RangeAccumulator rangeAccumulator = new RangeAccumulator(rangeRequests);
+ return MultiFacetsAccumulator.wrap(accumulator, rangeAccumulator);
+ }
}
/** Returns an empty {@link FacetResult}. */
@@ -89,69 +153,6 @@ public class FacetsAccumulator {
}
/**
- * Initializes the accumulator with the given parameters as well as
- * {@link FacetArrays}. Note that the accumulator doesn't call
- * {@link FacetArrays#free()}. If you require that (only makes sense if you
- * use {@link ReusingFacetArrays}, you should do it after you've finished with
- * the accumulator.
- */
- public FacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, TaxonomyReader taxonomyReader,
- FacetArrays facetArrays) {
- this.facetArrays = facetArrays;
- this.indexReader = indexReader;
- this.taxonomyReader = taxonomyReader;
- this.searchParams = searchParams;
- }
-
- /**
- * Returns the {@link FacetsAggregator} to use for aggregating the categories
- * found in the result documents. The default implementation returns
- * {@link CountingFacetsAggregator}, or {@link FastCountingFacetsAggregator}
- * if all categories can be decoded with {@link DGapVInt8IntDecoder}.
- */
- public FacetsAggregator getAggregator() {
- if (FastCountingFacetsAggregator.verifySearchParams(searchParams)) {
- return new FastCountingFacetsAggregator();
- } else {
- return new CountingFacetsAggregator();
- }
- }
-
- /**
- * Creates a {@link FacetResultsHandler} that matches the given
- * {@link FacetRequest}.
- */
- protected FacetResultsHandler createFacetResultsHandler(FacetRequest fr) {
- if (fr.getDepth() == 1 && fr.getSortOrder() == SortOrder.DESCENDING) {
- FacetArraysSource fas = fr.getFacetArraysSource();
- if (fas == FacetArraysSource.INT) {
- return new IntFacetResultsHandler(taxonomyReader, fr, facetArrays);
- }
-
- if (fas == FacetArraysSource.FLOAT) {
- return new FloatFacetResultsHandler(taxonomyReader, fr, facetArrays);
- }
- }
-
- if (fr.getResultMode() == ResultMode.PER_NODE_IN_TREE) {
- return new TopKInEachNodeHandler(taxonomyReader, fr, facetArrays);
- }
- return new TopKFacetResultsHandler(taxonomyReader, fr, facetArrays);
- }
-
- protected Set<CategoryListParams> getCategoryLists() {
- if (searchParams.indexingParams.getAllCategoryListParams().size() == 1) {
- return Collections.singleton(searchParams.indexingParams.getCategoryListParams(null));
- }
-
- HashSet<CategoryListParams> clps = new HashSet<CategoryListParams>();
- for (FacetRequest fr : searchParams.facetRequests) {
- clps.add(searchParams.indexingParams.getCategoryListParams(fr.categoryPath));
- }
- return clps;
- }
-
- /**
* Used by {@link FacetsCollector} to build the list of {@link FacetResult
* facet results} that match the {@link FacetRequest facet requests} that were
* given in the constructor.
@@ -159,44 +160,12 @@ public class FacetsAccumulator {
* @param matchingDocs
* the documents that matched the query, per-segment.
*/
- public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {
- // aggregate facets per category list (usually onle one category list)
- FacetsAggregator aggregator = getAggregator();
- for (CategoryListParams clp : getCategoryLists()) {
- for (MatchingDocs md : matchingDocs) {
- aggregator.aggregate(md, clp, facetArrays);
- }
- }
-
- ParallelTaxonomyArrays arrays = taxonomyReader.getParallelTaxonomyArrays();
-
- // compute top-K
- final int[] children = arrays.children();
- final int[] siblings = arrays.siblings();
- List<FacetResult> res = new ArrayList<FacetResult>();
- for (FacetRequest fr : searchParams.facetRequests) {
- int rootOrd = taxonomyReader.getOrdinal(fr.categoryPath);
- if (rootOrd == TaxonomyReader.INVALID_ORDINAL) { // category does not exist
- // Add empty FacetResult
- res.add(emptyResult(rootOrd, fr));
- continue;
- }
- CategoryListParams clp = searchParams.indexingParams.getCategoryListParams(fr.categoryPath);
- if (fr.categoryPath.length > 0) { // someone might ask to aggregate the ROOT category
- OrdinalPolicy ordinalPolicy = clp.getOrdinalPolicy(fr.categoryPath.components[0]);
- if (ordinalPolicy == OrdinalPolicy.NO_PARENTS) {
- // rollup values
- aggregator.rollupValues(fr, rootOrd, children, siblings, facetArrays);
- }
- }
-
- FacetResultsHandler frh = createFacetResultsHandler(fr);
- res.add(frh.compute());
- }
- return res;
- }
+ public abstract List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException;
- public boolean requiresDocScores() {
- return getAggregator().requiresDocScores();
- }
+ /**
+ * Used by {@link FacetsCollector} to determine if document scores need to be
+ * collected in addition to matching documents.
+ */
+ public abstract boolean requiresDocScores();
+
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java Mon Jul 29 13:07:30 2013
@@ -167,7 +167,7 @@ public abstract class FacetsCollector ex
* FacetsAccumulator} from {@link FacetsAccumulator#create}.
*/
public static FacetsCollector create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) {
- return create(FacetsAccumulator.create(fsp, indexReader, taxoReader));
+ return create(FacetsAccumulator.create(fsp, indexReader, taxoReader, null));
}
/**
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FastCountingFacetsAggregator.java Mon Jul 29 13:07:30 2013
@@ -5,7 +5,6 @@ import java.io.IOException;
import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder;
import org.apache.lucene.facet.encoding.DGapVInt8IntEncoder;
import org.apache.lucene.facet.params.CategoryListParams;
-import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.util.BytesRef;
@@ -40,23 +39,6 @@ public final class FastCountingFacetsAgg
private final BytesRef buf = new BytesRef(32);
- /**
- * Asserts that this {@link FacetsCollector} can handle the given
- * {@link FacetSearchParams}. Returns {@code null} if true, otherwise an error
- * message.
- */
- final static boolean verifySearchParams(FacetSearchParams fsp) {
- // verify that all category lists were encoded with DGapVInt
- for (FacetRequest fr : fsp.facetRequests) {
- CategoryListParams clp = fsp.indexingParams.getCategoryListParams(fr.categoryPath);
- if (clp.createEncoder().createMatchingDecoder().getClass() != DGapVInt8IntDecoder.class) {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public final void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays)
throws IOException {
Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java (from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetsAccumulatorWrapper.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetsAccumulatorWrapper.java&r1=1507930&r2=1508043&rev=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetsAccumulatorWrapper.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAccumulator.java Mon Jul 29 13:07:30 2013
@@ -1,4 +1,4 @@
-package org.apache.lucene.facet.range;
+package org.apache.lucene.facet.search;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,98 +20,50 @@ package org.apache.lucene.facet.range;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
-import org.apache.lucene.facet.params.CategoryListParams;
import org.apache.lucene.facet.params.FacetSearchParams;
-import org.apache.lucene.facet.search.FacetArrays;
-import org.apache.lucene.facet.search.FacetRequest;
import org.apache.lucene.facet.search.FacetResult;
-import org.apache.lucene.facet.search.FacetResultsHandler;
import org.apache.lucene.facet.search.FacetsAccumulator;
-import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
-import org.apache.lucene.facet.taxonomy.TaxonomyReader;
-import org.apache.lucene.index.IndexReader;
-/** Takes multiple facet requests and if necessary splits
- * them between the normal {@link FacetsAccumulator} and a
- * {@link RangeAccumulator} */
-public class RangeFacetsAccumulatorWrapper extends FacetsAccumulator {
- // TODO: somehow handle SortedSetDVAccumulator as
- // well... but it's tricky because SSDV just uses an
- // "ordinary" flat CountFacetRequest so we can't switch
- // based on that.
- private final FacetsAccumulator accumulator;
- private final RangeAccumulator rangeAccumulator;
-
- public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) {
- return create(fsp, indexReader, taxoReader, new FacetArrays(taxoReader.getSize()));
- }
-
- public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader, FacetArrays arrays) {
- List<FacetRequest> rangeRequests = new ArrayList<FacetRequest>();
- List<FacetRequest> nonRangeRequests = new ArrayList<FacetRequest>();
- for(FacetRequest fr : fsp.facetRequests) {
- if (fr instanceof RangeFacetRequest) {
- rangeRequests.add(fr);
- } else {
- nonRangeRequests.add(fr);
- }
- }
-
- if (rangeRequests.isEmpty()) {
- return new FacetsAccumulator(fsp, indexReader, taxoReader, arrays);
- } else if (nonRangeRequests.isEmpty()) {
- return new RangeAccumulator(fsp, indexReader);
+/**
+ * Wraps multiple {@link FacetsAccumulator} and returns a merged list of
+ * {@link FacetResult}, in the order the accumulators were given.
+ */
+public class MultiFacetsAccumulator extends FacetsAccumulator {
+
+ private final FacetsAccumulator[] accumulators;
+
+ /** Wraps the given {@link FacetsAccumulator accumulators}. */
+ public static FacetsAccumulator wrap(FacetsAccumulator... accumulators) {
+ if (accumulators.length == 0) {
+ return accumulators[0];
} else {
- FacetsAccumulator accumulator = new FacetsAccumulator(new FacetSearchParams(fsp.indexingParams, nonRangeRequests), indexReader, taxoReader, arrays);
- RangeAccumulator rangeAccumulator = new RangeAccumulator(new FacetSearchParams(fsp.indexingParams, rangeRequests), indexReader);
- return new RangeFacetsAccumulatorWrapper(accumulator, rangeAccumulator, fsp);
+ return new MultiFacetsAccumulator(accumulators);
}
}
- private RangeFacetsAccumulatorWrapper(FacetsAccumulator accumulator, RangeAccumulator rangeAccumulator, FacetSearchParams fsp) {
- super(fsp, accumulator.indexReader, accumulator.taxonomyReader);
- this.accumulator = accumulator;
- this.rangeAccumulator = rangeAccumulator;
- }
-
- @Override
- public FacetsAggregator getAggregator() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected FacetResultsHandler createFacetResultsHandler(FacetRequest fr) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- protected Set<CategoryListParams> getCategoryLists() {
- throw new UnsupportedOperationException();
+ private MultiFacetsAccumulator(FacetsAccumulator... accumulators) {
+ super((FacetSearchParams) null);
+ this.accumulators = accumulators;
}
@Override
public boolean requiresDocScores() {
- return accumulator.requiresDocScores();
+ for (FacetsAccumulator fa : accumulators) {
+ if (fa.requiresDocScores()) {
+ return true;
+ }
+ }
+ return false;
}
+ @Override
public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {
- List<FacetResult> results = accumulator.accumulate(matchingDocs);
- List<FacetResult> rangeResults = rangeAccumulator.accumulate(matchingDocs);
-
- int aUpto = 0;
- int raUpto = 0;
List<FacetResult> merged = new ArrayList<FacetResult>();
- for(FacetRequest fr : searchParams.facetRequests) {
- if (fr instanceof RangeFacetRequest) {
- merged.add(rangeResults.get(raUpto++));
- } else {
- merged.add(results.get(aUpto++));
- }
+ for (FacetsAccumulator fa : accumulators) {
+ merged.addAll(fa.accumulate(matchingDocs));
}
-
return merged;
}
}
Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java (from r1507930, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/MultiAssociationsFacetsAggregator.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/MultiAssociationsFacetsAggregator.java&r1=1507930&r2=1508043&rev=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/associations/MultiAssociationsFacetsAggregator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/MultiFacetsAggregator.java Mon Jul 29 13:07:30 2013
@@ -1,4 +1,4 @@
-package org.apache.lucene.facet.associations;
+package org.apache.lucene.facet.search;
import java.io.IOException;
import java.util.ArrayList;
@@ -39,22 +39,21 @@ import org.apache.lucene.facet.taxonomy.
*
* @lucene.experimental
*/
-public class MultiAssociationsFacetsAggregator implements FacetsAggregator {
+public class MultiFacetsAggregator implements FacetsAggregator {
private final Map<CategoryPath,FacetsAggregator> categoryAggregators;
private final List<FacetsAggregator> aggregators;
/**
- * Creates a new {@link MultiAssociationsFacetsAggregator} over the given
- * aggregators. The mapping is used by
- * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)} to
- * rollup the values of the specific category by the corresponding
- * {@link FacetsAggregator}. However, since each {@link FacetsAggregator}
- * handles the associations of a specific type, which could cover multiple
- * categories, the aggregation is done on the unique set of aggregators, which
- * are identified by their class.
+ * Constructor.
+ * <p>
+ * The mapping is used to rollup the values of the specific category by the
+ * corresponding {@link FacetsAggregator}. It is ok to pass differnet
+ * {@link FacetsAggregator} instances for each {@link CategoryPath} - the
+ * constructor ensures that each aggregator <u>type</u> (determined by its
+ * class) is invoked only once.
*/
- public MultiAssociationsFacetsAggregator(Map<CategoryPath,FacetsAggregator> aggregators) {
+ public MultiFacetsAggregator(Map<CategoryPath,FacetsAggregator> aggregators) {
this.categoryAggregators = aggregators;
// make sure that each FacetsAggregator class is invoked only once, or
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/PerCategoryListAggregator.java Mon Jul 29 13:07:30 2013
@@ -27,6 +27,9 @@ import org.apache.lucene.facet.search.Fa
/**
* A {@link FacetsAggregator} which invokes the proper aggregator per
* {@link CategoryListParams}.
+ * {@link #rollupValues(FacetRequest, int, int[], int[], FacetArrays)} is
+ * delegated to the proper aggregator which handles the
+ * {@link CategoryListParams} the given {@link FacetRequest} belongs to.
*/
public class PerCategoryListAggregator implements FacetsAggregator {
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java Mon Jul 29 13:07:30 2013
@@ -43,7 +43,7 @@ import org.apache.lucene.util.IntsRef;
*/
/**
- * Standard implementation for {@link FacetsAccumulator}, utilizing partitions to save on memory.
+ * Standard implementation for {@link TaxonomyFacetsAccumulator}, utilizing partitions to save on memory.
* <p>
* Why partitions? Because if there are say 100M categories out of which
* only top K are required, we must first compute value for all 100M categories
@@ -64,7 +64,7 @@ import org.apache.lucene.util.IntsRef;
*
* @lucene.experimental
*/
-public class StandardFacetsAccumulator extends FacetsAccumulator {
+public class StandardFacetsAccumulator extends TaxonomyFacetsAccumulator {
private static final Logger logger = Logger.getLogger(StandardFacetsAccumulator.class.getName());
@@ -96,15 +96,18 @@ public class StandardFacetsAccumulator e
private double complementThreshold = DEFAULT_COMPLEMENT_THRESHOLD;
- public StandardFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader,
+ private static FacetArrays createFacetArrays(FacetSearchParams searchParams, TaxonomyReader taxoReader) {
+ return new FacetArrays(PartitionsUtils.partitionSize(searchParams.indexingParams, taxoReader));
+ }
+
+ public StandardFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader,
TaxonomyReader taxonomyReader) {
- this(searchParams, indexReader, taxonomyReader, new FacetArrays(
- PartitionsUtils.partitionSize(searchParams.indexingParams, taxonomyReader)));
+ this(searchParams, indexReader, taxonomyReader, null);
}
public StandardFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader,
TaxonomyReader taxonomyReader, FacetArrays facetArrays) {
- super(searchParams, indexReader, taxonomyReader, facetArrays);
+ super(searchParams, indexReader, taxonomyReader, facetArrays == null ? createFacetArrays(searchParams, taxonomyReader) : facetArrays);
// can only be computed later when docids size is known
isUsingComplements = false;
@@ -126,8 +129,7 @@ public class StandardFacetsAccumulator e
if (isUsingComplements) {
try {
- totalFacetCounts = TotalFacetCountsCache.getSingleton().getTotalCounts(indexReader, taxonomyReader,
- searchParams.indexingParams);
+ totalFacetCounts = TotalFacetCountsCache.getSingleton().getTotalCounts(indexReader, taxonomyReader, searchParams.indexingParams);
if (totalFacetCounts != null) {
docids = ScoredDocIdsUtils.getComplementSet(docids, indexReader);
} else {
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/SumScoreFacetRequest.java Mon Jul 29 13:07:30 2013
@@ -1,5 +1,6 @@
package org.apache.lucene.facet.search;
+import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
@@ -34,6 +35,11 @@ public class SumScoreFacetRequest extend
}
@Override
+ public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
+ return new SumScoreFacetsAggregator();
+ }
+
+ @Override
public Aggregator createAggregator(boolean useComplements, FacetArrays arrays, TaxonomyReader taxonomy) {
assert !useComplements : "complements are not supported by this FacetRequest";
return new ScoringAggregator(arrays.getFloatArray());
Copied: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java (from r1507698, lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java)
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java?p2=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java&p1=lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java&r1=1507698&r2=1508043&rev=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/TaxonomyFacetsAccumulator.java Mon Jul 29 13:07:30 2013
@@ -3,18 +3,19 @@ package org.apache.lucene.facet.search;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
+import java.util.Map.Entry;
-import org.apache.lucene.facet.encoding.DGapVInt8IntDecoder;
import org.apache.lucene.facet.params.CategoryListParams;
-import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.params.CategoryListParams.OrdinalPolicy;
+import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.FacetRequest.FacetArraysSource;
import org.apache.lucene.facet.search.FacetRequest.ResultMode;
import org.apache.lucene.facet.search.FacetRequest.SortOrder;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
+import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.ParallelTaxonomyArrays;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.IndexReader;
@@ -37,84 +38,116 @@ import org.apache.lucene.index.IndexRead
*/
/**
- * Driver for Accumulating facets of faceted search requests over given
- * documents.
+ * A {@link FacetsAccumulator} suitable for accumulating categories that were
+ * indexed into a taxonomy index.
*
* @lucene.experimental
*/
-public class FacetsAccumulator {
+public class TaxonomyFacetsAccumulator extends FacetsAccumulator {
public final TaxonomyReader taxonomyReader;
public final IndexReader indexReader;
public final FacetArrays facetArrays;
- public FacetSearchParams searchParams;
-
+
/**
* Initializes the accumulator with the given search params, index reader and
* taxonomy reader. This constructor creates the default {@link FacetArrays},
* which do not support reuse. If you want to use {@link ReusingFacetArrays},
* you should use the
- * {@link #FacetsAccumulator(FacetSearchParams, IndexReader, TaxonomyReader, FacetArrays)}
+ * {@link #TaxonomyFacetsAccumulator(FacetSearchParams, IndexReader, TaxonomyReader)}
* constructor.
*/
- public FacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
- this(searchParams, indexReader, taxonomyReader, new FacetArrays(taxonomyReader.getSize()));
+ public TaxonomyFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader,
+ TaxonomyReader taxonomyReader) {
+ this(searchParams, indexReader, taxonomyReader, null);
}
/**
- * Creates an appropriate {@link FacetsAccumulator},
- * returning {@link FacetsAccumulator} when all requests
- * are {@link CountFacetRequest} and only one partition is
- * in use, otherwise {@link StandardFacetsAccumulator}.
- */
- public static FacetsAccumulator create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) {
- if (fsp.indexingParams.getPartitionSize() != Integer.MAX_VALUE) {
- return new StandardFacetsAccumulator(fsp, indexReader, taxoReader);
- }
-
- for (FacetRequest fr : fsp.facetRequests) {
- if (!(fr instanceof CountFacetRequest)) {
- return new StandardFacetsAccumulator(fsp, indexReader, taxoReader);
- }
- }
-
- return new FacetsAccumulator(fsp, indexReader, taxoReader);
- }
-
- /** Returns an empty {@link FacetResult}. */
- protected static FacetResult emptyResult(int ordinal, FacetRequest fr) {
- FacetResultNode root = new FacetResultNode(ordinal, 0);
- root.label = fr.categoryPath;
- return new FacetResult(fr, root, 0);
- }
-
- /**
* Initializes the accumulator with the given parameters as well as
* {@link FacetArrays}. Note that the accumulator doesn't call
* {@link FacetArrays#free()}. If you require that (only makes sense if you
* use {@link ReusingFacetArrays}, you should do it after you've finished with
* the accumulator.
*/
- public FacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader, TaxonomyReader taxonomyReader,
- FacetArrays facetArrays) {
- this.facetArrays = facetArrays;
+ public TaxonomyFacetsAccumulator(FacetSearchParams searchParams, IndexReader indexReader,
+ TaxonomyReader taxonomyReader, FacetArrays facetArrays) {
+ super(searchParams);
+ this.facetArrays = facetArrays == null ? new FacetArrays(taxonomyReader.getSize()) : facetArrays;
this.indexReader = indexReader;
this.taxonomyReader = taxonomyReader;
- this.searchParams = searchParams;
}
-
+
+ /** Group all requests that belong to the same {@link CategoryListParams}. */
+ protected Map<CategoryListParams,List<FacetRequest>> groupRequests() {
+ if (searchParams.indexingParams.getAllCategoryListParams().size() == 1) {
+ return Collections.singletonMap(searchParams.indexingParams.getCategoryListParams(null), searchParams.facetRequests);
+ }
+
+ HashMap<CategoryListParams,List<FacetRequest>> requestsPerCLP = new HashMap<CategoryListParams,List<FacetRequest>>();
+ for (FacetRequest fr : searchParams.facetRequests) {
+ CategoryListParams clp = searchParams.indexingParams.getCategoryListParams(fr.categoryPath);
+ List<FacetRequest> requests = requestsPerCLP.get(clp);
+ if (requests == null) {
+ requests = new ArrayList<FacetRequest>();
+ requestsPerCLP.put(clp, requests);
+ }
+ requests.add(fr);
+ }
+ return requestsPerCLP;
+ }
+
/**
* Returns the {@link FacetsAggregator} to use for aggregating the categories
- * found in the result documents. The default implementation returns
- * {@link CountingFacetsAggregator}, or {@link FastCountingFacetsAggregator}
- * if all categories can be decoded with {@link DGapVInt8IntDecoder}.
+ * found in the result documents.
*/
public FacetsAggregator getAggregator() {
- if (FastCountingFacetsAggregator.verifySearchParams(searchParams)) {
- return new FastCountingFacetsAggregator();
- } else {
- return new CountingFacetsAggregator();
+ Map<CategoryListParams,List<FacetRequest>> requestsPerCLP = groupRequests();
+
+ // optimize for all-CountFacetRequest and single category list (common case)
+ if (requestsPerCLP.size() == 1) {
+ boolean allCount = true;
+ for (FacetRequest fr : searchParams.facetRequests) {
+ if (!(fr instanceof CountFacetRequest)) {
+ allCount = false;
+ break;
+ }
+ }
+ if (allCount) {
+ return requestsPerCLP.values().iterator().next().get(0).createFacetsAggregator(searchParams.indexingParams);
+ }
+ }
+
+ // If we're here it means the facet requests are spread across multiple
+ // category lists, or there are multiple types of facet requests, or both.
+ // Therefore create a per-CategoryList mapping of FacetsAggregators.
+ Map<CategoryListParams,FacetsAggregator> perCLPAggregator = new HashMap<CategoryListParams,FacetsAggregator>();
+ for (Entry<CategoryListParams,List<FacetRequest>> e : requestsPerCLP.entrySet()) {
+ CategoryListParams clp = e.getKey();
+ List<FacetRequest> requests = e.getValue();
+ Map<Class<? extends FacetsAggregator>,FacetsAggregator> aggClasses = new HashMap<Class<? extends FacetsAggregator>,FacetsAggregator>();
+ Map<CategoryPath,FacetsAggregator> perCategoryAggregator = new HashMap<CategoryPath,FacetsAggregator>();
+ for (FacetRequest fr : requests) {
+ FacetsAggregator fa = fr.createFacetsAggregator(searchParams.indexingParams);
+ if (fa == null) {
+ throw new IllegalArgumentException("this accumulator only supports requests that create a FacetsAggregator: " + fr);
+ }
+ Class<? extends FacetsAggregator> faClass = fa.getClass();
+ if (!aggClasses.containsKey(faClass)) {
+ aggClasses.put(faClass, fa);
+ } else {
+ fa = aggClasses.get(faClass);
+ }
+ perCategoryAggregator.put(fr.categoryPath, fa);
+ }
+
+ if (aggClasses.size() == 1) { // only one type of facet request
+ perCLPAggregator.put(clp, aggClasses.values().iterator().next());
+ } else {
+ perCLPAggregator.put(clp, new MultiFacetsAggregator(perCategoryAggregator));
+ }
}
+
+ return new PerCategoryListAggregator(perCLPAggregator, searchParams.indexingParams);
}
/**
@@ -139,18 +172,6 @@ public class FacetsAccumulator {
return new TopKFacetResultsHandler(taxonomyReader, fr, facetArrays);
}
- protected Set<CategoryListParams> getCategoryLists() {
- if (searchParams.indexingParams.getAllCategoryListParams().size() == 1) {
- return Collections.singleton(searchParams.indexingParams.getCategoryListParams(null));
- }
-
- HashSet<CategoryListParams> clps = new HashSet<CategoryListParams>();
- for (FacetRequest fr : searchParams.facetRequests) {
- clps.add(searchParams.indexingParams.getCategoryListParams(fr.categoryPath));
- }
- return clps;
- }
-
/**
* Used by {@link FacetsCollector} to build the list of {@link FacetResult
* facet results} that match the {@link FacetRequest facet requests} that were
@@ -159,10 +180,11 @@ public class FacetsAccumulator {
* @param matchingDocs
* the documents that matched the query, per-segment.
*/
+ @Override
public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {
// aggregate facets per category list (usually onle one category list)
FacetsAggregator aggregator = getAggregator();
- for (CategoryListParams clp : getCategoryLists()) {
+ for (CategoryListParams clp : groupRequests().keySet()) {
for (MatchingDocs md : matchingDocs) {
aggregator.aggregate(md, clp, facetArrays);
}
@@ -196,6 +218,7 @@ public class FacetsAccumulator {
return res;
}
+ @Override
public boolean requiresDocScores() {
return getAggregator().requiresDocScores();
}
Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java?rev=1508043&r1=1508042&r2=1508043&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/sortedset/SortedSetDocValuesAccumulator.java Mon Jul 29 13:07:30 2013
@@ -32,19 +32,19 @@ import org.apache.lucene.facet.search.Fa
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsAccumulator;
-import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
+import org.apache.lucene.facet.search.TaxonomyFacetsAccumulator;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.index.AtomicReader;
import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
import org.apache.lucene.index.MultiDocValues;
+import org.apache.lucene.index.MultiDocValues.MultiSortedSetDocValues;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.PriorityQueue;
-/** A {@link FacetsAccumulator} that uses previously
+/** A {@link TaxonomyFacetsAccumulator} that uses previously
* indexed {@link SortedSetDocValuesFacetFields} to perform faceting,
* without require a separate taxonomy index. Faceting is
* a bit slower (~25%), and there is added cost on every
@@ -57,25 +57,34 @@ public class SortedSetDocValuesAccumulat
final SortedSetDocValuesReaderState state;
final SortedSetDocValues dv;
final String field;
-
- public SortedSetDocValuesAccumulator(FacetSearchParams fsp, SortedSetDocValuesReaderState state) throws IOException {
- super(fsp, null, null, new FacetArrays(state.getSize()));
+ final FacetArrays facetArrays;
+
+ /** Constructor with the given facet search params. */
+ public SortedSetDocValuesAccumulator(SortedSetDocValuesReaderState state, FacetSearchParams fsp)
+ throws IOException {
+ this(state, fsp, null);
+ }
+
+ public SortedSetDocValuesAccumulator(SortedSetDocValuesReaderState state, FacetSearchParams fsp, FacetArrays arrays)
+ throws IOException {
+ super(fsp);
this.state = state;
this.field = state.getField();
+ this.facetArrays = arrays == null ? new FacetArrays(state.getSize()) : arrays;
dv = state.getDocValues();
// Check params:
- for(FacetRequest request : fsp.facetRequests) {
- if (!(request instanceof CountFacetRequest)) {
- throw new IllegalArgumentException("this collector only supports CountFacetRequest; got " + request);
+ for (FacetRequest fr : fsp.facetRequests) {
+ if (!(fr instanceof CountFacetRequest)) {
+ throw new IllegalArgumentException("this accumulator only supports CountFacetRequest; got " + fr);
}
- if (request.categoryPath.length != 1) {
- throw new IllegalArgumentException("this collector only supports depth 1 CategoryPath; got " + request.categoryPath);
+ if (fr.categoryPath.length != 1) {
+ throw new IllegalArgumentException("this accumulator only supports 1-level CategoryPath; got " + fr.categoryPath);
}
- if (request.getDepth() != 1) {
- throw new IllegalArgumentException("this collector only supports depth=1; got " + request.getDepth());
+ if (fr.getDepth() != 1) {
+ throw new IllegalArgumentException("this accumulator only supports depth=1; got " + fr.getDepth());
}
- String dim = request.categoryPath.components[0];
+ String dim = fr.categoryPath.components[0];
SortedSetDocValuesReaderState.OrdRange ordRange = state.getOrdRange(dim);
if (ordRange == null) {
@@ -84,131 +93,123 @@ public class SortedSetDocValuesAccumulat
}
}
- @Override
- public FacetsAggregator getAggregator() {
+ /** Keeps highest count results. */
+ static class TopCountPQ extends PriorityQueue<FacetResultNode> {
+ public TopCountPQ(int topN) {
+ super(topN, false);
+ }
+
+ @Override
+ protected boolean lessThan(FacetResultNode a, FacetResultNode b) {
+ if (a.value < b.value) {
+ return true;
+ } else if (a.value > b.value) {
+ return false;
+ } else {
+ return a.ordinal > b.ordinal;
+ }
+ }
+ }
- return new FacetsAggregator() {
+ static class SortedSetAggregator {
- @Override
- public void aggregate(MatchingDocs matchingDocs, CategoryListParams clp, FacetArrays facetArrays) throws IOException {
+ private final SortedSetDocValuesReaderState state;
+ private final String field;
+ private final SortedSetDocValues dv;
+
+ public SortedSetAggregator(String field, SortedSetDocValuesReaderState state, SortedSetDocValues dv) {
+ this.field = field;
+ this.state = state;
+ this.dv = dv;
+ }
+
+ public void aggregate(MatchingDocs matchingDocs, FacetArrays facetArrays) throws IOException {
- AtomicReader reader = matchingDocs.context.reader();
+ AtomicReader reader = matchingDocs.context.reader();
- // LUCENE-5090: make sure the provided reader context "matches"
- // the top-level reader passed to the
- // SortedSetDocValuesReaderState, else cryptic
- // AIOOBE can happen:
- if (ReaderUtil.getTopLevelContext(matchingDocs.context).reader() != state.origReader) {
- throw new IllegalStateException("the SortedSetDocValuesReaderState provided to this class does not match the reader being searched; you must create a new SortedSetDocValuesReaderState every time you open a new IndexReader");
- }
-
- SortedSetDocValues segValues = reader.getSortedSetDocValues(field);
- if (segValues == null) {
- return;
- }
+ // LUCENE-5090: make sure the provided reader context "matches"
+ // the top-level reader passed to the
+ // SortedSetDocValuesReaderState, else cryptic
+ // AIOOBE can happen:
+ if (ReaderUtil.getTopLevelContext(matchingDocs.context).reader() != state.origReader) {
+ throw new IllegalStateException("the SortedSetDocValuesReaderState provided to this class does not match the reader being searched; you must create a new SortedSetDocValuesReaderState every time you open a new IndexReader");
+ }
+
+ SortedSetDocValues segValues = reader.getSortedSetDocValues(field);
+ if (segValues == null) {
+ return;
+ }
- final int[] counts = facetArrays.getIntArray();
- final int maxDoc = reader.maxDoc();
- assert maxDoc == matchingDocs.bits.length();
-
- if (dv instanceof MultiSortedSetDocValues) {
- MultiDocValues.OrdinalMap ordinalMap = ((MultiSortedSetDocValues) dv).mapping;
- int segOrd = matchingDocs.context.ord;
-
- int numSegOrds = (int) segValues.getValueCount();
-
- if (matchingDocs.totalHits < numSegOrds/10) {
- // Remap every ord to global ord as we iterate:
- int doc = 0;
- while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
- segValues.setDocument(doc);
- int term = (int) segValues.nextOrd();
- while (term != SortedSetDocValues.NO_MORE_ORDS) {
- counts[(int) ordinalMap.getGlobalOrd(segOrd, term)]++;
- term = (int) segValues.nextOrd();
- }
- ++doc;
- }
- } else {
+ final int[] counts = facetArrays.getIntArray();
+ final int maxDoc = reader.maxDoc();
+ assert maxDoc == matchingDocs.bits.length();
- // First count in seg-ord space:
- final int[] segCounts = new int[numSegOrds];
- int doc = 0;
- while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
- segValues.setDocument(doc);
- int term = (int) segValues.nextOrd();
- while (term != SortedSetDocValues.NO_MORE_ORDS) {
- segCounts[term]++;
- term = (int) segValues.nextOrd();
- }
- ++doc;
- }
+ if (dv instanceof MultiSortedSetDocValues) {
+ MultiDocValues.OrdinalMap ordinalMap = ((MultiSortedSetDocValues) dv).mapping;
+ int segOrd = matchingDocs.context.ord;
- // Then, migrate to global ords:
- for(int ord=0;ord<numSegOrds;ord++) {
- int count = segCounts[ord];
- if (count != 0) {
- counts[(int) ordinalMap.getGlobalOrd(segOrd, ord)] += count;
- }
+ int numSegOrds = (int) segValues.getValueCount();
+
+ if (matchingDocs.totalHits < numSegOrds/10) {
+ // Remap every ord to global ord as we iterate:
+ int doc = 0;
+ while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
+ segValues.setDocument(doc);
+ int term = (int) segValues.nextOrd();
+ while (term != SortedSetDocValues.NO_MORE_ORDS) {
+ counts[(int) ordinalMap.getGlobalOrd(segOrd, term)]++;
+ term = (int) segValues.nextOrd();
}
+ ++doc;
}
} else {
- // No ord mapping (e.g., single segment index):
- // just aggregate directly into counts:
+ // First count in seg-ord space:
+ final int[] segCounts = new int[numSegOrds];
int doc = 0;
while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
segValues.setDocument(doc);
int term = (int) segValues.nextOrd();
while (term != SortedSetDocValues.NO_MORE_ORDS) {
- counts[term]++;
+ segCounts[term]++;
term = (int) segValues.nextOrd();
}
++doc;
}
- }
- }
- @Override
- public void rollupValues(FacetRequest fr, int ordinal, int[] children, int[] siblings, FacetArrays facetArrays) {
- // Nothing to do here: we only support flat (dim +
- // label) facets, and in accumulate we sum up the
- // count for the dimension.
- }
+ // Then, migrate to global ords:
+ for(int ord=0;ord<numSegOrds;ord++) {
+ int count = segCounts[ord];
+ if (count != 0) {
+ counts[(int) ordinalMap.getGlobalOrd(segOrd, ord)] += count;
+ }
+ }
+ }
+ } else {
+ // No ord mapping (e.g., single segment index):
+ // just aggregate directly into counts:
- @Override
- public boolean requiresDocScores() {
- return false;
+ int doc = 0;
+ while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
+ segValues.setDocument(doc);
+ int term = (int) segValues.nextOrd();
+ while (term != SortedSetDocValues.NO_MORE_ORDS) {
+ counts[term]++;
+ term = (int) segValues.nextOrd();
+ }
+ ++doc;
+ }
}
- };
- }
-
- /** Keeps highest count results. */
- static class TopCountPQ extends PriorityQueue<FacetResultNode> {
- public TopCountPQ(int topN) {
- super(topN, false);
}
- @Override
- protected boolean lessThan(FacetResultNode a, FacetResultNode b) {
- if (a.value < b.value) {
- return true;
- } else if (a.value > b.value) {
- return false;
- } else {
- return a.ordinal > b.ordinal;
- }
- }
}
-
+
@Override
public List<FacetResult> accumulate(List<MatchingDocs> matchingDocs) throws IOException {
- FacetsAggregator aggregator = getAggregator();
- for (CategoryListParams clp : getCategoryLists()) {
- for (MatchingDocs md : matchingDocs) {
- aggregator.aggregate(md, clp, facetArrays);
- }
+ SortedSetAggregator aggregator = new SortedSetAggregator(field, state, dv);
+ for (MatchingDocs md : matchingDocs) {
+ aggregator.aggregate(md, facetArrays);
}
// compute top-K
@@ -218,7 +219,7 @@ public class SortedSetDocValuesAccumulat
BytesRef scratch = new BytesRef();
- for(FacetRequest request : searchParams.facetRequests) {
+ for (FacetRequest request : searchParams.facetRequests) {
String dim = request.categoryPath.components[0];
SortedSetDocValuesReaderState.OrdRange ordRange = state.getOrdRange(dim);
// checked in ctor:
@@ -315,4 +316,10 @@ public class SortedSetDocValuesAccumulat
return results;
}
+
+ @Override
+ public boolean requiresDocScores() {
+ return false;
+ }
+
}