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/11/05 05:37:16 UTC
svn commit: r1538864 - in /lucene/dev/branches/branch_4x: ./ lucene/
lucene/CHANGES.txt lucene/facet/
lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java
lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java
Author: shaie
Date: Tue Nov 5 04:37:14 2013
New Revision: 1538864
URL: http://svn.apache.org/r1538864
Log:
LUCENE-5297: allow range faceting on any ValueSource
Modified:
lucene/dev/branches/branch_4x/ (props changed)
lucene/dev/branches/branch_4x/lucene/ (props changed)
lucene/dev/branches/branch_4x/lucene/CHANGES.txt (contents, props changed)
lucene/dev/branches/branch_4x/lucene/facet/ (props changed)
lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java
lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java
Modified: lucene/dev/branches/branch_4x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/CHANGES.txt?rev=1538864&r1=1538863&r2=1538864&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/lucene/CHANGES.txt Tue Nov 5 04:37:14 2013
@@ -87,6 +87,9 @@ New Features
* LUCENE-5312: Add BlockJoinSorter, a new Sorter implementation that makes sure
to never split up blocks of documents indexed with IndexWriter.addDocuments.
(Adrien Grand)
+
+* LUCENE-5297: Allow to range-facet on any ValueSource, not just
+ NumericDocValues fields. (Shai Erera)
Bug Fixes
Modified: lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java?rev=1538864&r1=1538863&r2=1538864&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java (original)
+++ lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeAccumulator.java Tue Nov 5 04:37:14 2013
@@ -28,29 +28,15 @@ import org.apache.lucene.facet.search.Fa
import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsAccumulator;
import org.apache.lucene.facet.search.FacetsCollector.MatchingDocs;
-import org.apache.lucene.facet.taxonomy.CategoryPath;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.util.Bits;
-
-/** Uses a {@link NumericDocValues} and accumulates
- * counts for provided ranges. This is dynamic (does not
- * use the taxonomy index or anything from the index
- * except the NumericDocValuesField). */
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.queries.function.FunctionValues;
+/**
+ * Uses {@link RangeFacetRequest#getValues(AtomicReaderContext)} and accumulates
+ * counts for provided ranges.
+ */
public class RangeAccumulator extends FacetsAccumulator {
- static class RangeSet {
- final Range[] ranges;
- final String field;
-
- public RangeSet(Range[] ranges, String field) {
- this.ranges = ranges;
- this.field = field;
- }
- }
-
- final List<RangeSet> requests = new ArrayList<RangeSet>();
-
public RangeAccumulator(FacetRequest... facetRequests) {
this(Arrays.asList(facetRequests));
}
@@ -65,9 +51,6 @@ public class RangeAccumulator extends Fa
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, fr.categoryPath.components[0]));
}
}
@@ -78,35 +61,29 @@ public class RangeAccumulator extends Fa
// 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++) {
- RangeSet ranges = requests.get(i);
-
- int[] counts = new int[ranges.ranges.length];
+ for (FacetRequest req : searchParams.facetRequests) {
+ RangeFacetRequest<?> rangeFR = (RangeFacetRequest<?>) req;
+ int[] counts = new int[rangeFR.ranges.length];
for (MatchingDocs hits : matchingDocs) {
- NumericDocValues ndv = hits.context.reader().getNumericDocValues(ranges.field);
- if (ndv == null) {
- continue; // no numeric values for this field in this reader
- }
- Bits docsWithField = hits.context.reader().getDocsWithField(ranges.field);
-
+ FunctionValues fv = rangeFR.getValues(hits.context);
final int length = hits.bits.length();
int doc = 0;
while (doc < length && (doc = hits.bits.nextSetBit(doc)) != -1) {
- long v = ndv.get(doc);
-
// Skip missing docs:
- if (v == 0 && docsWithField.get(doc) == false) {
- doc++;
+ if (!fv.exists(doc)) {
+ ++doc;
continue;
}
+
+ long v = fv.longVal(doc);
// TODO: if all ranges are non-overlapping, we
// should instead do a bin-search up front
// (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++) {
- if (ranges.ranges[j].accept(v)) {
+ for (int j = 0; j < rangeFR.ranges.length; j++) {
+ if (rangeFR.ranges[j].accept(v)) {
counts[j]++;
}
}
@@ -114,19 +91,19 @@ public class RangeAccumulator extends Fa
doc++;
}
}
-
- List<FacetResultNode> nodes = new ArrayList<FacetResultNode>(ranges.ranges.length);
- for(int j=0;j<ranges.ranges.length;j++) {
- nodes.add(new RangeFacetResultNode(ranges.field, ranges.ranges[j], counts[j]));
+
+ List<FacetResultNode> nodes = new ArrayList<FacetResultNode>(rangeFR.ranges.length);
+ for (int j = 0; j < rangeFR.ranges.length; j++) {
+ nodes.add(new RangeFacetResultNode(rangeFR.label, rangeFR.ranges[j], counts[j]));
}
-
+
FacetResultNode rootNode = new FacetResultNode(-1, 0);
- rootNode.label = new CategoryPath(ranges.field);
+ rootNode.label = rangeFR.categoryPath;
rootNode.subResults = nodes;
- results.add(new FacetResult(searchParams.facetRequests.get(i), rootNode, nodes.size()));
+ results.add(new FacetResult(req, rootNode, nodes.size()));
}
-
+
return results;
}
Modified: lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java?rev=1538864&r1=1538863&r2=1538864&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java (original)
+++ lucene/dev/branches/branch_4x/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetRequest.java Tue Nov 5 04:37:14 2013
@@ -17,38 +17,91 @@ package org.apache.lucene.facet.range;
* limitations under the License.
*/
+import java.io.IOException;
+import java.util.Collections;
import java.util.List;
import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.search.FacetRequest;
+import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsAggregator;
import org.apache.lucene.facet.taxonomy.CategoryPath;
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.queries.function.FunctionValues;
+import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.queries.function.valuesource.LongFieldSource;
/**
- * Facet request for dynamic ranges based on a
- * NumericDocValues field. This does not use the taxonomy
- * index nor any indexed facet values.
+ * A {@link FacetRequest} for dynamic ranges based on a {@link NumericDocValues}
+ * field or {@link ValueSource}. This does not use the taxonomy index nor any
+ * indexed facet values.
*
* @lucene.experimental
*/
public class RangeFacetRequest<T extends Range> extends FacetRequest {
public final Range[] ranges;
-
+ public final String label;
+
+ private final ValueSource valueSource;
+
+ /**
+ * Create a request for the given ranges over the specified
+ * {@link NumericDocValues} field. The field will be used to as the root's
+ * {@link FacetResultNode} label.
+ */
@SuppressWarnings("unchecked")
public RangeFacetRequest(String field, T...ranges) {
- super(new CategoryPath(field), 1);
- this.ranges = ranges;
+ this(field, new LongFieldSource(field), ranges);
}
+ /**
+ * Create a request for the given ranges over the specified
+ * {@link NumericDocValues} field. The field will be used to as the root's
+ * {@link FacetResultNode} label.
+ */
@SuppressWarnings("unchecked")
public RangeFacetRequest(String field, List<T> ranges) {
this(field, (T[]) ranges.toArray(new Range[ranges.size()]));
}
+
+ /**
+ * Create a request for the given ranges over the specified
+ * {@link ValueSource}. The label will be used to as the root's
+ * {@link FacetResultNode} label.
+ */
+ @SuppressWarnings("unchecked")
+ public RangeFacetRequest(String label, ValueSource valueSource, T...ranges) {
+ super(new CategoryPath(label), 1);
+ this.ranges = ranges;
+ this.valueSource = valueSource;
+ this.label = label;
+ }
+
+ /**
+ * Create a request for the given ranges over the specified
+ * {@link ValueSource}. The label will be used to as the root's
+ * {@link FacetResultNode} label.
+ */
+ @SuppressWarnings("unchecked")
+ public RangeFacetRequest(String label, ValueSource valueSource, List<T> ranges) {
+ this(label, valueSource, (T[]) ranges.toArray(new Range[ranges.size()]));
+ }
+ /**
+ * Returns the {@link FunctionValues} for the given
+ * {@link AtomicReaderContext}. If the request was created over a
+ * {@link NumericDocValues} field, the respective {@link NumericDocValues} is
+ * returned.
+ */
+ public FunctionValues getValues(AtomicReaderContext context) throws IOException {
+ return valueSource.getValues(Collections.emptyMap(), context);
+ }
+
@Override
public FacetsAggregator createFacetsAggregator(FacetIndexingParams fip) {
- return null;
+ throw new UnsupportedOperationException("this FacetRequest does not support categories aggregation and only works with RangeAccumulator");
}
}