Index: lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java
===================================================================
--- lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java (revision 1434923)
+++ lucene/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLSearcher.java (working copy)
@@ -109,8 +109,7 @@
// behavior - in those
// situations other, more low-level interfaces are available, as
// demonstrated in other search examples.
- FacetsCollector facetsCollector = new FacetsCollector(
- facetSearchParams, indexReader, taxo);
+ FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxo);
// perform documents search and facets accumulation
searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector));
Index: lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java
===================================================================
--- lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java (revision 1434923)
+++ lucene/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleSearcher.java (working copy)
@@ -104,9 +104,9 @@
}
// Faceted search parameters indicate which facets are we interested in
- FacetSearchParams facetSearchParams = new FacetSearchParams(Arrays.asList(facetRequests), indexingParams);
+ FacetSearchParams facetSearchParams = new FacetSearchParams(indexingParams, facetRequests);
- FacetsCollector facetsCollector = new FacetsCollector(facetSearchParams, indexReader, taxoReader);
+ FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, indexReader, taxoReader);
// perform documents search and facets accumulation
searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector));
Index: lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsCollector.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsCollector.java (revision 0)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsCollector.java (working copy)
@@ -0,0 +1,336 @@
+package org.apache.lucene.facet.search;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.lucene.facet.index.categorypolicy.OrdinalPolicy;
+import org.apache.lucene.facet.index.params.CategoryListParams;
+import org.apache.lucene.facet.index.params.FacetIndexingParams;
+import org.apache.lucene.facet.search.params.CountFacetRequest;
+import org.apache.lucene.facet.search.params.FacetRequest;
+import org.apache.lucene.facet.search.params.FacetSearchParams;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.search.results.FacetResultNode;
+import org.apache.lucene.facet.taxonomy.CategoryPath;
+import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.facet.taxonomy.directory.ParallelTaxonomyArrays;
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.PriorityQueue;
+import org.apache.lucene.util.encoding.DGapVInt8IntDecoder;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A {@link Collector} which counts facets associated with matching documents.
+ * This {@link Collector} can be used only in the following conditions:
+ *
+ * - All {@link FacetRequest requests} must be {@link CountFacetRequest}.
+ * Also, their {@link FacetRequest#getDepth()} must return 1.
+ *
- Partitions should be disabled (
+ * {@link FacetIndexingParams#getPartitionSize()} should return
+ * Integer.MAX_VALUE).
+ *
- There can be only one {@link CategoryListParams} in the
+ * {@link FacetIndexingParams}, with {@link DGapVInt8IntDecoder}.
+ *
- {@link FacetIndexingParams#getOrdinalPolicy()} must be
+ * {@link OrdinalPolicy#ALL_PARENTS}.
+ *
+ */
+public class CountingFacetsCollector extends FacetsCollector {
+
+ private final FacetSearchParams fsp;
+ private final TaxonomyReader taxoReader;
+ private final BytesRef buf = new BytesRef(32);
+ private final FacetArrays facetArrays;
+ private final int[] counts;
+ private final String facetsField;
+
+ private DocValues.Source facetsSource;
+
+ public CountingFacetsCollector(FacetSearchParams fsp, TaxonomyReader taxoReader) {
+ this(fsp, taxoReader, new FacetArrays(taxoReader.getSize()));
+ }
+
+ public CountingFacetsCollector(FacetSearchParams fsp, TaxonomyReader taxoReader, FacetArrays facetArrays) {
+ assert facetArrays.arrayLength >= taxoReader.getSize() : "too small facet array";
+ assert assertParams(fsp) == null : assertParams(fsp);
+
+ this.fsp = fsp;
+ this.taxoReader = taxoReader;
+ this.facetArrays = facetArrays;
+ this.counts = facetArrays.getIntArray();
+ this.facetsField = fsp.indexingParams.getCategoryListParams(null).field;
+ }
+
+ /**
+ * Asserts that this {@link FacetsCollector} can handle the given
+ * {@link FacetSearchParams}. Returns {@code null} if true, otherwise an error
+ * message.
+ */
+ static String assertParams(FacetSearchParams fsp) {
+ // verify that all facet requests are CountFacetRequest
+ for (FacetRequest fr : fsp.facetRequests) {
+ if (!(fr instanceof CountFacetRequest)) {
+ return "all FacetRequests must be CountFacetRequest";
+ }
+ if (fr.getDepth() != 1) {
+ return "all requests must be of depth 1";
+ }
+ if (fr.getNumLabel() < fr.getNumResults()) {
+ return "this Collector always labels all requested results";
+ }
+ }
+
+ // verify that there's only one CategoryListParams
+ List clps = fsp.indexingParams.getAllCategoryListParams();
+ if (clps.size() != 1) {
+ return "this Collector supports only one CategoryListParams";
+ }
+
+ // verify DGapVInt decoder
+ CategoryListParams clp = clps.get(0);
+ if (clp.createEncoder().createMatchingDecoder().getClass() != DGapVInt8IntDecoder.class) {
+ return "this Collector supports only DGap + VInt encoding";
+ }
+
+ // verify that partitions are disabled
+ if (fsp.indexingParams.getPartitionSize() != Integer.MAX_VALUE) {
+ return "this Collector does not support partitions";
+ }
+
+ // verify that all parents are indexed
+ if (fsp.indexingParams.getOrdinalPolicy() != OrdinalPolicy.ALL_PARENTS) {
+ return "this Collector assumes that all of a category's parents are indexed";
+ }
+
+ return null;
+ }
+
+ @Override
+ public void setNextReader(AtomicReaderContext context) throws IOException {
+ DocValues dv = context.reader().docValues(facetsField);
+ if (dv == null) {
+ facetsSource = null;
+ } else {
+ facetsSource = dv.getSource();
+ }
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ if (facetsSource == null) {
+ return;
+ }
+
+ facetsSource.getBytes(doc, buf);
+ if (buf.length == 0) {
+ // this document has no facets
+ }
+
+ int upto = buf.offset + buf.length;
+ int ord = 0;
+ int offset = buf.offset;
+ int prev = 0;
+ while (offset < upto) {
+ byte b = buf.bytes[offset++];
+ if (b >= 0) {
+ prev = ord = ((ord << 7) | b) + prev;
+ counts[ord]++;
+ ord = 0;
+ } else {
+ ord = (ord << 7) | (b & 0x7F);
+ }
+ }
+ }
+
+ @Override
+ public synchronized List getFacetResults() throws IOException {
+ try {
+ ParallelTaxonomyArrays arrays = taxoReader.getParallelTaxonomyArrays();
+ final int[] children = arrays.children();
+ final int[] siblings = arrays.siblings();
+ List res = new ArrayList();
+ for (FacetRequest fr : fsp.facetRequests) {
+ int rootOrd = taxoReader.getOrdinal(fr.categoryPath);
+ if (rootOrd == TaxonomyReader.INVALID_ORDINAL) { // category does not exist
+ continue;
+ }
+ // since we use sentinel objects, we cannot reuse PQ. but that's ok because it's not big
+ // nocommit specialize for Integer.MAX_VALUE? Or any value that's larger than taxoSize?
+ OrdinalsQueue pq = new OrdinalsQueue(fr.getNumResults(), true);
+ OrdinalValue top = pq.top();
+ int child = children[rootOrd];
+ int numResults = 0; // count the number of results
+ int residue = 0;
+ while (child != TaxonomyReader.INVALID_ORDINAL) {
+ int count = counts[child];
+ if (count > top.value) {
+ residue += top.value;
+ top.value = count;
+ top.ordinal = child;
+ top = pq.updateTop();
+ ++numResults;
+ } else {
+ residue += count;
+ }
+ child = siblings[child];
+ }
+
+ // since we populate the queue w/ sentinel objects, need to pop() the
+ // least ones (which are sentinel)
+ int pqsize = pq.size();
+ int size = numResults < pqsize ? numResults : pqsize;
+ for (int i = pqsize - size; i > 0; i--) { pq.pop(); }
+
+ // create the FacetResultNodes. first pop() the queue into an array, and later label
+ FacetResultNode[] subResults = new FacetResultNode[size];
+ for (int i = size - 1; i >= 0; i--) {
+ OrdinalValue ov = pq.pop();
+ CategoryPath cp = taxoReader.getPath(ov.ordinal);
+ FacetResultNodeImpl sub = new FacetResultNodeImpl(ov.ordinal, cp, null, ov.value, 0);
+ subResults[i] = sub;
+ }
+ FacetResultNode root = new FacetResultNodeImpl(rootOrd, fr.categoryPath, Arrays.asList(subResults), counts[rootOrd], residue);
+ FacetResult fres = new FacetResult(fr, root, size);
+ res.add(fres);
+ }
+ return res;
+ } finally {
+ facetArrays.free();
+ }
+ }
+
+ @Override
+ public boolean acceptsDocsOutOfOrder() {
+ // in-memory DocValues are random access
+ return true;
+ }
+
+ @Override
+ public void setScorer(Scorer scorer) throws IOException {
+ }
+
+ private static class OrdinalValue {
+ OrdinalValue() {}
+ public int value = 0;
+ public int ordinal = -1;
+
+ @Override
+ public String toString() {
+ return "ordinal=" + ordinal + " value=" + value;
+ }
+ }
+
+ private static class OrdinalsQueue extends PriorityQueue {
+
+ public OrdinalsQueue(int maxSize, boolean prepopulate) {
+ super(maxSize, prepopulate);
+ }
+
+ @Override
+ protected OrdinalValue getSentinelObject() {
+ return new OrdinalValue();
+ }
+
+ @Override
+ protected boolean lessThan(OrdinalValue a, OrdinalValue b) {
+ if (a.value < b.value) return true;
+ if (a.value > b.value) return false;
+ // both have the same value, break tie by ordinal
+ return a.ordinal < b.ordinal;
+ }
+
+ }
+
+ // nocommit use MutableFRN? If so, use this class as the instance to put in the queue?
+ private static class FacetResultNodeImpl implements FacetResultNode {
+
+ private final int ordinal;
+ private final CategoryPath cp;
+ private final List subResults;
+ private final double residue;
+
+ private double value;
+
+ public FacetResultNodeImpl(int ordinal, CategoryPath cp, List subResults, double value, double residue) {
+ this.ordinal = ordinal;
+ this.cp = cp;
+ this.subResults = subResults == null ? Collections.emptyList() : subResults;
+ this.residue = residue;
+ this.value = value;
+ }
+
+ @Override
+ public String toString(String prefix) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(prefix).append(cp.toString()).append(" (").append(Double.toString(value)).append(")");
+ for (FacetResultNode sub : subResults) {
+ sb.append("\n").append(prefix).append(sub.toString(prefix));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int getOrdinal() {
+ return ordinal;
+ }
+
+ @Override
+ public CategoryPath getLabel() {
+ return cp;
+ }
+
+ @Override
+ public CategoryPath getLabel(TaxonomyReader taxonomyReader) throws IOException {
+ return cp;
+ }
+
+ @Override
+ public double getValue() {
+ return value;
+ }
+
+ @Override
+ public double getResidue() {
+ return residue;
+ }
+
+ @Override
+ public Iterable extends FacetResultNode> getSubResults() {
+ return subResults;
+ }
+
+ @Override
+ public int getNumSubResults() {
+ return subResults == null ? 0 : subResults.size();
+ }
+
+ @Override
+ public void setValue(double value) {
+ this.value = value;
+ }
+
+ }
+
+}
Property changes on: lucene/facet/src/java/org/apache/lucene/facet/search/CountingFacetsCollector.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/DrillDown.java (working copy)
@@ -47,7 +47,7 @@
* @see #term(FacetIndexingParams, CategoryPath)
*/
public static final Term term(FacetSearchParams sParams, CategoryPath path) {
- return term(sParams.getFacetIndexingParams(), path);
+ return term(sParams.indexingParams, path);
}
/** Return a drill-down {@link Term} for a category. */
@@ -103,7 +103,7 @@
* @see #query(FacetIndexingParams, Query, CategoryPath...)
*/
public static final Query query(FacetSearchParams sParams, Query baseQuery, CategoryPath... paths) {
- return query(sParams.getFacetIndexingParams(), baseQuery, paths);
+ return query(sParams.indexingParams, baseQuery, paths);
}
}
Index: lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (working copy)
@@ -138,7 +138,7 @@
/** check if all requests are complementable */
protected boolean mayComplement() {
- for (FacetRequest freq:searchParams.getFacetRequests()) {
+ for (FacetRequest freq:searchParams.facetRequests) {
if (!freq.supportsComplements()) {
return false;
}
Index: lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/FacetsCollector.java (working copy)
@@ -3,15 +3,13 @@
import java.io.IOException;
import java.util.List;
-import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.Collector;
-import org.apache.lucene.search.Scorer;
-
import org.apache.lucene.facet.search.params.FacetRequest;
import org.apache.lucene.facet.search.params.FacetSearchParams;
import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.Collector;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -31,109 +29,31 @@
*/
/**
- * Collector for facet accumulation. *
+ * A {@link Collector} which executes faceted search and computes the weight of
+ * requested facets. To get the facet results you should call
+ * {@link #getFacetResults()}.
+ * {@link #create(FacetSearchParams, IndexReader, TaxonomyReader)} returns the
+ * most optimized {@link FacetsCollector} for the given parameters.
*
* @lucene.experimental
*/
-public class FacetsCollector extends Collector {
-
- protected final FacetsAccumulator facetsAccumulator;
- private ScoredDocIdCollector scoreDocIdCollector;
- private List results;
- private Object resultsGuard;
-
- /**
- * Create a collector for accumulating facets while collecting documents
- * during search.
- *
- * @param facetSearchParams
- * faceted search parameters defining which facets are required and
- * how.
- * @param indexReader
- * searched index.
- * @param taxonomyReader
- * taxonomy containing the facets.
- */
- public FacetsCollector(FacetSearchParams facetSearchParams,
- IndexReader indexReader, TaxonomyReader taxonomyReader) {
- facetsAccumulator = initFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
- scoreDocIdCollector = initScoredDocCollector(facetSearchParams, indexReader, taxonomyReader);
- resultsGuard = new Object();
- }
-
- /**
- * Create a {@link ScoredDocIdCollector} to be used as the first phase of
- * the facet collection. If all facetRequests are do not require the
- * document score, a ScoredDocIdCollector which does not store the document
- * scores would be returned. Otherwise a SDIC which does store the documents
- * will be returned, having an initial allocated space for 1000 such
- * documents' scores.
- */
- protected ScoredDocIdCollector initScoredDocCollector(
- FacetSearchParams facetSearchParams, IndexReader indexReader,
- TaxonomyReader taxonomyReader) {
- boolean scoresNeeded = false;
- for (FacetRequest frq : facetSearchParams.getFacetRequests()) {
- if (frq.requireDocumentScore()) {
- scoresNeeded = true;
- break;
- }
+public abstract class FacetsCollector extends Collector {
+
+ // nocommit javadocs
+ public static FacetsCollector create(FacetSearchParams fsp, IndexReader indexReader, TaxonomyReader taxoReader) {
+ if (CountingFacetsCollector.assertParams(fsp) == null) {
+ return new CountingFacetsCollector(fsp, taxoReader);
}
- return ScoredDocIdCollector.create(indexReader.maxDoc(), scoresNeeded);
+
+ return new StandardFacetsCollector(fsp, indexReader, taxoReader);
}
-
+
/**
- * Create the {@link FacetsAccumulator} to be used. Default is
- * {@link StandardFacetsAccumulator}. Called once at the constructor of the collector.
- *
- * @param facetSearchParams
- * The search params.
- * @param indexReader
- * A reader to the index to search in.
- * @param taxonomyReader
- * A reader to the active taxonomy.
- * @return The {@link FacetsAccumulator} to use.
+ * Returns a {@link FacetResult} per {@link FacetRequest} set in
+ * {@link FacetSearchParams}. Note that if one of the {@link FacetRequest
+ * requests} is for a {@link CategoryPath} that does not exist in the taxonomy,
+ * no matching {@link FacetResult} will be returned.
*/
- protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams,
- IndexReader indexReader,
- TaxonomyReader taxonomyReader) {
- return new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
- }
+ public abstract List getFacetResults() throws IOException;
- /**
- * Return accumulated facets results (according to faceted search parameters)
- * for collected documents.
- * @throws IOException on error
- */
- public List getFacetResults() throws IOException {
- synchronized (resultsGuard) { // over protection
- if (results == null) {
- // lazy creation but just once
- results = facetsAccumulator.accumulate(scoreDocIdCollector.getScoredDocIDs());
- scoreDocIdCollector = null;
- }
- return results;
- }
- }
-
- @Override
- public boolean acceptsDocsOutOfOrder() {
- return false;
- }
-
- @Override
- public void collect(int doc) throws IOException {
- scoreDocIdCollector.collect(doc);
- }
-
- @Override
- public void setNextReader(AtomicReaderContext context) throws IOException {
- scoreDocIdCollector.setNextReader(context);
- }
-
- @Override
- public void setScorer(Scorer scorer) throws IOException {
- scoreDocIdCollector.setScorer(scorer);
- }
-
}
Index: lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsAccumulator.java (working copy)
@@ -87,7 +87,7 @@
this.facetArrays = facetArrays;
// can only be computed later when docids size is known
isUsingComplements = false;
- partitionSize = PartitionsUtils.partitionSize(searchParams.getFacetIndexingParams(), taxonomyReader);
+ partitionSize = PartitionsUtils.partitionSize(searchParams.indexingParams, taxonomyReader);
maxPartitions = (int) Math.ceil(this.taxonomyReader.getSize() / (double) partitionSize);
accumulateGuard = new Object();
}
@@ -95,7 +95,7 @@
public StandardFacetsAccumulator(FacetSearchParams searchParams,
IndexReader indexReader, TaxonomyReader taxonomyReader) {
this(searchParams, indexReader, taxonomyReader, new FacetArrays(
- PartitionsUtils.partitionSize(searchParams.getFacetIndexingParams(), taxonomyReader)));
+ PartitionsUtils.partitionSize(searchParams.indexingParams, taxonomyReader)));
}
@Override
@@ -112,7 +112,7 @@
if (isUsingComplements) {
try {
totalFacetCounts = TotalFacetCountsCache.getSingleton().getTotalCounts(indexReader, taxonomyReader,
- searchParams.getFacetIndexingParams());
+ searchParams.indexingParams);
if (totalFacetCounts != null) {
docids = ScoredDocIdsUtils.getComplementSet(docids, indexReader);
} else {
@@ -159,7 +159,7 @@
// In this implementation merges happen after each partition,
// but other impl could merge only at the end.
final HashSet handledRequests = new HashSet();
- for (FacetRequest fr : searchParams.getFacetRequests()) {
+ for (FacetRequest fr : searchParams.facetRequests) {
// Handle and merge only facet requests which were not already handled.
if (handledRequests.add(fr)) {
FacetResultsHandler frHndlr = fr.createFacetResultsHandler(taxonomyReader);
@@ -178,7 +178,7 @@
// gather results from all requests into a list for returning them
List res = new ArrayList();
- for (FacetRequest fr : searchParams.getFacetRequests()) {
+ for (FacetRequest fr : searchParams.facetRequests) {
FacetResultsHandler frHndlr = fr.createFacetResultsHandler(taxonomyReader);
IntermediateFacetResult tmpResult = fr2tmpRes.get(fr);
if (tmpResult == null) {
@@ -321,8 +321,8 @@
HashMap categoryLists = new HashMap();
- FacetIndexingParams indexingParams = searchParams.getFacetIndexingParams();
- for (FacetRequest facetRequest : searchParams.getFacetRequests()) {
+ FacetIndexingParams indexingParams = searchParams.indexingParams;
+ for (FacetRequest facetRequest : searchParams.facetRequests) {
Aggregator categoryAggregator = facetRequest.createAggregator(isUsingComplements, facetArrays, taxonomyReader);
CategoryListIterator cli = indexingParams.getCategoryListParams(facetRequest.categoryPath).createCategoryListIterator(partition);
Index: lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsCollector.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsCollector.java (revision 0)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsCollector.java (working copy)
@@ -0,0 +1,132 @@
+package org.apache.lucene.facet.search;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.lucene.facet.search.params.FacetRequest;
+import org.apache.lucene.facet.search.params.FacetSearchParams;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.Scorer;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A {@link FacetsCollector} which allows initilizing e.g.
+ * {@link FacetsAccumulator}.
+ *
+ * @lucene.experimental
+ */
+public class StandardFacetsCollector extends FacetsCollector {
+
+ protected final FacetsAccumulator facetsAccumulator;
+ private ScoredDocIdCollector scoreDocIdCollector;
+ private List results;
+ private Object resultsGuard;
+
+ /**
+ * Create a collector for accumulating facets while collecting documents
+ * during search.
+ *
+ * @param facetSearchParams
+ * faceted search parameters defining which facets are required and
+ * how.
+ * @param indexReader
+ * searched index.
+ * @param taxonomyReader
+ * taxonomy containing the facets.
+ */
+ public StandardFacetsCollector(FacetSearchParams facetSearchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
+ facetsAccumulator = initFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
+ scoreDocIdCollector = initScoredDocCollector(facetSearchParams, indexReader, taxonomyReader);
+ resultsGuard = new Object();
+ }
+
+ /**
+ * Create a {@link ScoredDocIdCollector} to be used as the first phase of
+ * the facet collection. If all facetRequests are do not require the
+ * document score, a ScoredDocIdCollector which does not store the document
+ * scores would be returned. Otherwise a SDIC which does store the documents
+ * will be returned, having an initial allocated space for 1000 such
+ * documents' scores.
+ */
+ protected ScoredDocIdCollector initScoredDocCollector(FacetSearchParams facetSearchParams, IndexReader indexReader,
+ TaxonomyReader taxonomyReader) {
+ boolean scoresNeeded = false;
+ for (FacetRequest frq : facetSearchParams.facetRequests) {
+ if (frq.requireDocumentScore()) {
+ scoresNeeded = true;
+ break;
+ }
+ }
+ return ScoredDocIdCollector.create(indexReader.maxDoc(), scoresNeeded);
+ }
+
+ /**
+ * Create the {@link FacetsAccumulator} to be used. Default is
+ * {@link StandardFacetsAccumulator}. Called once at the constructor of the collector.
+ *
+ * @param facetSearchParams
+ * The search params.
+ * @param indexReader
+ * A reader to the index to search in.
+ * @param taxonomyReader
+ * A reader to the active taxonomy.
+ * @return The {@link FacetsAccumulator} to use.
+ */
+ protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams,
+ IndexReader indexReader,
+ TaxonomyReader taxonomyReader) {
+ return new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
+ }
+
+ @Override
+ public List getFacetResults() throws IOException {
+ synchronized (resultsGuard) { // over protection
+ if (results == null) {
+ // lazy creation but just once
+ results = facetsAccumulator.accumulate(scoreDocIdCollector.getScoredDocIDs());
+ scoreDocIdCollector = null;
+ }
+ return results;
+ }
+ }
+
+ @Override
+ public boolean acceptsDocsOutOfOrder() {
+ return false;
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ scoreDocIdCollector.collect(doc);
+ }
+
+ @Override
+ public void setNextReader(AtomicReaderContext context) throws IOException {
+ scoreDocIdCollector.setNextReader(context);
+ }
+
+ @Override
+ public void setScorer(Scorer scorer) throws IOException {
+ scoreDocIdCollector.setScorer(scorer);
+ }
+
+}
Property changes on: lucene/facet/src/java/org/apache/lucene/facet/search/StandardFacetsCollector.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/facet/src/java/org/apache/lucene/facet/search/TotalFacetCounts.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/TotalFacetCounts.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/TotalFacetCounts.java (working copy)
@@ -8,9 +8,7 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.lucene.facet.index.params.CategoryListParams;
@@ -150,14 +148,13 @@
}
// needed because FacetSearchParams do not allow empty FacetRequests
- private static final List DUMMY_REQ = Arrays.asList(
- new FacetRequest[] { new CountFacetRequest(CategoryPath.EMPTY, 1) });
+ private static final FacetRequest DUMMY_REQ = new CountFacetRequest(CategoryPath.EMPTY, 1);
static TotalFacetCounts compute(final IndexReader indexReader, final TaxonomyReader taxonomy,
final FacetIndexingParams facetIndexingParams) throws IOException {
int partitionSize = PartitionsUtils.partitionSize(facetIndexingParams, taxonomy);
final int[][] counts = new int[(int) Math.ceil(taxonomy.getSize() /(float) partitionSize)][partitionSize];
- FacetSearchParams newSearchParams = new FacetSearchParams(DUMMY_REQ, facetIndexingParams);
+ FacetSearchParams newSearchParams = new FacetSearchParams(facetIndexingParams, DUMMY_REQ);
//createAllListsSearchParams(facetIndexingParams, this.totalCounts);
FacetsAccumulator fe = new StandardFacetsAccumulator(newSearchParams, indexReader, taxonomy) {
@Override
Index: lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetSearchParams.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetSearchParams.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetSearchParams.java (working copy)
@@ -35,8 +35,8 @@
*/
public class FacetSearchParams {
- protected final FacetIndexingParams indexingParams;
- protected final List facetRequests;
+ public final FacetIndexingParams indexingParams;
+ public final List facetRequests;
/**
* Initializes with the given {@link FacetRequest requests} and default
@@ -57,6 +57,14 @@
public FacetSearchParams(List facetRequests) {
this(facetRequests, FacetIndexingParams.ALL_PARENTS);
}
+
+ /**
+ * Initilizes with the given {@link FacetRequest requests} and
+ * {@link FacetIndexingParams}.
+ */
+ public FacetSearchParams(FacetIndexingParams indexingParams, FacetRequest... facetRequests) {
+ this(Arrays.asList(facetRequests), indexingParams);
+ }
/**
* Initilizes with the given {@link FacetRequest requests} and
@@ -66,36 +74,20 @@
if (facetRequests == null || facetRequests.size() == 0) {
throw new IllegalArgumentException("at least one FacetRequest must be defined");
}
+ this.facetRequests = facetRequests;
this.indexingParams = indexingParams;
- this.facetRequests = facetRequests;
}
- /**
- * Returns the {@link FacetIndexingParams} that were passed to the
- * constructor.
- */
- public FacetIndexingParams getFacetIndexingParams() {
- return indexingParams;
- }
-
- /**
- * Returns the list of {@link FacetRequest facet requests} that were passed to
- * the constructor.
- */
- public List getFacetRequests() {
- return facetRequests;
- }
-
@Override
public String toString() {
final char TAB = '\t';
final char NEWLINE = '\n';
StringBuilder sb = new StringBuilder("IndexingParams: ");
- sb.append(NEWLINE).append(TAB).append(getFacetIndexingParams());
+ sb.append(NEWLINE).append(TAB).append(indexingParams);
sb.append(NEWLINE).append("FacetRequests:");
- for (FacetRequest facetRequest : getFacetRequests()) {
+ for (FacetRequest facetRequest : facetRequests) {
sb.append(NEWLINE).append(TAB).append(facetRequest);
}
Index: lucene/facet/src/java/org/apache/lucene/facet/search/results/MutableFacetResultNode.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/results/MutableFacetResultNode.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/results/MutableFacetResultNode.java (working copy)
@@ -196,13 +196,6 @@
return value;
}
- /**
- * Set the value of this result.
- *
- * @param value
- * the value to set
- * @see #getValue()
- */
@Override
public void setValue(double value) {
this.value = value;
@@ -222,11 +215,6 @@
return residue;
}
- /**
- * Set the residue.
- * @param residue the residue to set
- * @see #getResidue()
- */
public void setResidue(double residue) {
this.residue = residue;
}
@@ -308,27 +296,14 @@
subResults.add(0, subRes);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.apache.lucene.facet.search.results.FacetResultNode#getLabel(org.apache.lucene
- * .facet.taxonomy.TaxonomyReader)
- */
@Override
- public final CategoryPath getLabel(TaxonomyReader taxonomyReader)
- throws IOException {
+ public final CategoryPath getLabel(TaxonomyReader taxonomyReader) throws IOException {
if (label == null) {
label = taxonomyReader.getPath(ordinal);
}
return label;
}
- /*
- * (non-Javadoc)
- *
- * @see org.apache.lucene.facet.search.results.FacetResultNode#getNumSubResults()
- */
@Override
public final int getNumSubResults() {
return subResults == null ? 0 : subResults.size();
Index: lucene/facet/src/java/org/apache/lucene/facet/search/sampling/Sampler.java
===================================================================
--- lucene/facet/src/java/org/apache/lucene/facet/search/sampling/Sampler.java (revision 1434923)
+++ lucene/facet/src/java/org/apache/lucene/facet/search/sampling/Sampler.java (working copy)
@@ -184,11 +184,11 @@
double overSampleFactor = getSamplingParams().getOversampleFactor();
if (overSampleFactor > 1) { // any factoring to do?
List facetRequests = new ArrayList();
- for (FacetRequest frq : original.getFacetRequests()) {
+ for (FacetRequest frq : original.facetRequests) {
int overSampledNumResults = (int) Math.ceil(frq.getNumResults() * overSampleFactor);
facetRequests.add(new OverSampledFacetRequest(frq, overSampledNumResults));
}
- res = new FacetSearchParams(facetRequests, original.getFacetIndexingParams());
+ res = new FacetSearchParams(facetRequests, original.indexingParams);
}
return res;
}
Index: lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (working copy)
@@ -196,7 +196,7 @@
* test with different faceted search params.
*/
protected FacetSearchParams getFacetSearchParams(FacetIndexingParams iParams, FacetRequest... facetRequests) {
- return new FacetSearchParams(Arrays.asList(facetRequests), iParams);
+ return new FacetSearchParams(iParams, facetRequests);
}
/**
@@ -315,33 +315,18 @@
assertCountsAndCardinality(facetCountsTruth, subRes, reqNumResults); // recurse into child results
}
}
-
+
/** Validate results equality */
protected static void assertSameResults(List expected, List actual) {
- String expectedResults = resStringValueOnly(expected);
- String actualResults = resStringValueOnly(actual);
- if (!expectedResults.equals(actualResults)) {
- System.err.println("Results are not the same!");
- System.err.println("Expected:\n" + expectedResults);
- System.err.println("Actual:\n" + actualResults);
- throw new NotSameResultError();
+ assertEquals("wrong number of facet results", expected.size(), actual.size());
+ int size = expected.size();
+ for (int i = 0; i < size; i++) {
+ FacetResult expectedResult = expected.get(i);
+ FacetResult actualResult = actual.get(i);
+ String expectedStr = FacetTestUtils.toSimpleString(expectedResult);
+ String actualStr = FacetTestUtils.toSimpleString(actualResult);
+ assertEquals("Results not the same!\nExpected:" + expectedStr + "\nActual:\n" + actualStr, expectedStr, actualStr);
}
}
- /** exclude the residue and numDecendants because it is incorrect in sampling */
- private static final String resStringValueOnly(List results) {
- StringBuilder sb = new StringBuilder();
- for (FacetResult facetRes : results) {
- sb.append(facetRes.toString()).append('\n');
- }
- return sb.toString().replaceAll("Residue:.*.0", "").replaceAll("Num valid Descendants.*", "");
- }
-
- /** Special Error class for ability to ignore only this error and retry... */
- public static class NotSameResultError extends Error {
- public NotSameResultError() {
- super("Results are not the same!");
- }
- }
-
}
Index: lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java (working copy)
@@ -10,6 +10,8 @@
import org.apache.lucene.facet.search.params.CountFacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest;
import org.apache.lucene.facet.search.params.FacetSearchParams;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.search.results.FacetResultNode;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
@@ -45,6 +47,33 @@
public class FacetTestUtils {
+ public static class IndexTaxonomyReaderPair {
+ public DirectoryReader indexReader;
+ public DirectoryTaxonomyReader taxReader;
+ public IndexSearcher indexSearcher;
+
+ public void close() throws IOException {
+ indexReader.close();
+ taxReader.close();
+ }
+
+ }
+
+ public static class IndexTaxonomyWriterPair {
+ public IndexWriter indexWriter;
+ public TaxonomyWriter taxWriter;
+
+ public void close() throws IOException {
+ indexWriter.close();
+ taxWriter.close();
+ }
+
+ public void commit() throws IOException {
+ indexWriter.commit();
+ taxWriter.commit();
+ }
+ }
+
public static Directory[][] createIndexTaxonomyDirs(int number) {
Directory[][] dirs = new Directory[number][2];
for (int i = 0; i < number; i++) {
@@ -54,8 +83,7 @@
return dirs;
}
- public static IndexTaxonomyReaderPair[] createIndexTaxonomyReaderPair(
- Directory[][] dirs) throws IOException {
+ public static IndexTaxonomyReaderPair[] createIndexTaxonomyReaderPair(Directory[][] dirs) throws IOException {
IndexTaxonomyReaderPair[] pairs = new IndexTaxonomyReaderPair[dirs.length];
for (int i = 0; i < dirs.length; i++) {
IndexTaxonomyReaderPair pair = new IndexTaxonomyReaderPair();
@@ -66,15 +94,13 @@
}
return pairs;
}
-
- public static IndexTaxonomyWriterPair[] createIndexTaxonomyWriterPair(
- Directory[][] dirs) throws IOException {
+
+ public static IndexTaxonomyWriterPair[] createIndexTaxonomyWriterPair(Directory[][] dirs) throws IOException {
IndexTaxonomyWriterPair[] pairs = new IndexTaxonomyWriterPair[dirs.length];
for (int i = 0; i < dirs.length; i++) {
IndexTaxonomyWriterPair pair = new IndexTaxonomyWriterPair();
pair.indexWriter = new IndexWriter(dirs[i][0], new IndexWriterConfig(
- LuceneTestCase.TEST_VERSION_CURRENT, new StandardAnalyzer(
- LuceneTestCase.TEST_VERSION_CURRENT)));
+ LuceneTestCase.TEST_VERSION_CURRENT, new StandardAnalyzer(LuceneTestCase.TEST_VERSION_CURRENT)));
pair.taxWriter = new DirectoryTaxonomyWriter(dirs[i][1]);
pair.indexWriter.commit();
pair.taxWriter.commit();
@@ -83,9 +109,8 @@
return pairs;
}
- public static Collector[] search(IndexSearcher searcher,
- TaxonomyReader taxonomyReader, FacetIndexingParams iParams, int k,
- String... facetNames) throws IOException {
+ public static Collector[] search(IndexSearcher searcher, TaxonomyReader taxonomyReader, FacetIndexingParams iParams,
+ int k, String... facetNames) throws IOException {
Collector[] collectors = new Collector[2];
@@ -97,10 +122,8 @@
}
FacetSearchParams facetSearchParams = new FacetSearchParams(fRequests, iParams);
- TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(
- searcher.getIndexReader().maxDoc(), true);
- FacetsCollector facetsCollector = new FacetsCollector(
- facetSearchParams, searcher.getIndexReader(), taxonomyReader);
+ TopScoreDocCollector topDocsCollector = TopScoreDocCollector.create(searcher.getIndexReader().maxDoc(), true);
+ FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, searcher.getIndexReader(), taxonomyReader);
Collector mColl = MultiCollector.wrap(topDocsCollector, facetsCollector);
collectors[0] = topDocsCollector;
@@ -109,32 +132,18 @@
searcher.search(new MatchAllDocsQuery(), mColl);
return collectors;
}
-
- public static class IndexTaxonomyReaderPair {
- public DirectoryReader indexReader;
- public DirectoryTaxonomyReader taxReader;
- public IndexSearcher indexSearcher;
- public void close() throws IOException {
- indexReader.close();
- taxReader.close();
- }
-
+ public static String toSimpleString(FacetResult fr) {
+ StringBuilder sb = new StringBuilder();
+ toSimpleString(0, sb, fr.getFacetResultNode(), "");
+ return sb.toString();
}
- public static class IndexTaxonomyWriterPair {
- public IndexWriter indexWriter;
- public TaxonomyWriter taxWriter;
-
- public void close() throws IOException {
- indexWriter.close();
- taxWriter.close();
+ private static void toSimpleString(int depth, StringBuilder sb, FacetResultNode node, String indent) {
+ sb.append(indent + node.getLabel().components[depth] + " (" + (int) node.getValue() + ")\n");
+ for(FacetResultNode childNode : node.getSubResults()) {
+ toSimpleString(depth + 1, sb, childNode, indent + " ");
}
-
- public void commit() throws IOException {
- indexWriter.commit();
- taxWriter.commit();
- }
}
}
Index: lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/index/OrdinalMappingReaderTest.java (working copy)
@@ -71,7 +71,7 @@
DirectoryTaxonomyReader taxReader = new DirectoryTaxonomyReader(taxDir);
IndexSearcher searcher = newSearcher(reader1);
FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("tag"), NUM_DOCS));
- FacetsCollector collector = new FacetsCollector(fsp, reader1, taxReader);
+ FacetsCollector collector = FacetsCollector.create(fsp, reader1, taxReader);
searcher.search(new MatchAllDocsQuery(), collector);
FacetResult result = collector.getFacetResults().get(0);
FacetResultNode node = result.getFacetResultNode();
Index: lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/index/TestFacetsPayloadMigrationReader.java (working copy)
@@ -266,7 +266,7 @@
requests.add(new CountFacetRequest(new CategoryPath(dim), 5));
}
FacetSearchParams fsp = new FacetSearchParams(requests, fip);
- FacetsCollector fc = new FacetsCollector(fsp, indexReader, taxoReader);
+ FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader);
MatchAllDocsQuery base = new MatchAllDocsQuery();
searcher.search(base, fc);
List facetResults = fc.getFacetResults();
@@ -283,12 +283,10 @@
// verify drill-down
for (String dim : expectedCounts.keySet()) {
CategoryPath drillDownCP = new CategoryPath(dim);
- ArrayList request = new ArrayList(1);
- request.add(new CountFacetRequest(drillDownCP, 10));
- FacetSearchParams fsp = new FacetSearchParams(request, fip);
+ FacetSearchParams fsp = new FacetSearchParams(fip, new CountFacetRequest(drillDownCP, 10));
Query drillDown = DrillDown.query(fsp, new MatchAllDocsQuery(), drillDownCP);
TotalHitCountCollector total = new TotalHitCountCollector();
- FacetsCollector fc = new FacetsCollector(fsp, indexReader, taxoReader);
+ FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader);
searcher.search(drillDown, MultiCollector.wrap(fc, total));
assertTrue("no results for drill-down query " + drillDown, total.getTotalHits() > 0);
List facetResults = fc.getFacetResults();
Index: lucene/facet/src/test/org/apache/lucene/facet/search/CountingFacetsCollectorTest.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/CountingFacetsCollectorTest.java (revision 0)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/CountingFacetsCollectorTest.java (working copy)
@@ -0,0 +1,393 @@
+package org.apache.lucene.facet.search;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.facet.index.FacetFields;
+import org.apache.lucene.facet.index.categorypolicy.OrdinalPolicy;
+import org.apache.lucene.facet.index.params.CategoryListParams;
+import org.apache.lucene.facet.index.params.FacetIndexingParams;
+import org.apache.lucene.facet.search.params.CountFacetRequest;
+import org.apache.lucene.facet.search.params.FacetRequest;
+import org.apache.lucene.facet.search.params.FacetSearchParams;
+import org.apache.lucene.facet.search.params.ScoreFacetRequest;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.search.results.FacetResultNode;
+import org.apache.lucene.facet.taxonomy.CategoryPath;
+import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
+import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
+import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.NoMergePolicy;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.collections.ObjectToIntMap;
+import org.apache.lucene.util.encoding.IntEncoder;
+import org.apache.lucene.util.encoding.VInt8IntEncoder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class CountingFacetsCollectorTest extends LuceneTestCase {
+
+ private static final Term A = new Term("f", "a");
+ private static final CategoryPath CP_A = new CategoryPath("A"), CP_B = new CategoryPath("B");
+ private static final int NUM_CHILDREN_CP_A = 5, NUM_CHILDREN_CP_B = 3;
+ private static final CategoryPath[] CATEGORIES_A, CATEGORIES_B;
+ static {
+ CATEGORIES_A = new CategoryPath[NUM_CHILDREN_CP_A];
+ for (int i = 0; i < NUM_CHILDREN_CP_A; i++) {
+ CATEGORIES_A[i] = new CategoryPath(CP_A.components[0], Integer.toString(i));
+ }
+ CATEGORIES_B = new CategoryPath[NUM_CHILDREN_CP_B];
+ for (int i = 0; i < NUM_CHILDREN_CP_B; i++) {
+ CATEGORIES_B[i] = new CategoryPath(CP_B.components[0], Integer.toString(i));
+ }
+ }
+
+ private static Directory indexDir, taxoDir;
+ private static ObjectToIntMap allExpectedCounts, termExpectedCounts;
+ private static int numChildrenIndexedA, numChildrenIndexedB;
+
+ @AfterClass
+ public static void afterClassCountingFacetsCollectorTest() throws Exception {
+ IOUtils.close(indexDir, taxoDir);
+ }
+
+ private static List randomCategories(Random random) {
+ // add random categories from the two dimensions, ensuring that the same
+ // category is not added twice.
+ int numFacetsA = random.nextInt(3) + 1; // 1-3
+ int numFacetsB = random.nextInt(2) + 1; // 1-2
+ ArrayList categories_a = new ArrayList();
+ categories_a.addAll(Arrays.asList(CATEGORIES_A));
+ ArrayList categories_b = new ArrayList();
+ categories_b.addAll(Arrays.asList(CATEGORIES_B));
+ Collections.shuffle(categories_a, random);
+ Collections.shuffle(categories_b, random);
+
+ ArrayList categories = new ArrayList();
+ categories.addAll(categories_a.subList(0, numFacetsA));
+ categories.addAll(categories_b.subList(0, numFacetsB));
+ return categories;
+ }
+
+ private static void addField(Document doc) {
+ doc.add(new StringField(A.field(), A.text(), Store.NO));
+ }
+
+ private static void addFacets(Document doc, FacetFields facetFields, boolean updateTermExpectedCounts)
+ throws IOException {
+ List docCategories = randomCategories(random());
+ for (CategoryPath cp : docCategories) {
+ allExpectedCounts.put(cp, allExpectedCounts.get(cp) + 1);
+ if (updateTermExpectedCounts) {
+ termExpectedCounts.put(cp, termExpectedCounts.get(cp) + 1);
+ }
+ }
+ // add 1 to each dimension
+ allExpectedCounts.put(CP_A, allExpectedCounts.get(CP_A) + 1);
+ allExpectedCounts.put(CP_B, allExpectedCounts.get(CP_B) + 1);
+ if (updateTermExpectedCounts) {
+ termExpectedCounts.put(CP_A, termExpectedCounts.get(CP_A) + 1);
+ termExpectedCounts.put(CP_B, termExpectedCounts.get(CP_B) + 1);
+ }
+
+ facetFields.addFields(doc, docCategories);
+ }
+
+ private static void indexDocsNoFacets(IndexWriter indexWriter) throws IOException {
+ int numDocs = atLeast(2);
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ addField(doc);
+ indexWriter.addDocument(doc);
+ }
+ indexWriter.commit(); // flush a segment
+ }
+
+ private static void indexDocsWithFacetsNoTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter,
+ ObjectToIntMap expectedCounts) throws IOException {
+ Random random = random();
+ int numDocs = atLeast(random, 2);
+ FacetFields facetFields = new FacetFields(taxoWriter);
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ addFacets(doc, facetFields, false);
+ indexWriter.addDocument(doc);
+ }
+ indexWriter.commit(); // flush a segment
+ }
+
+ private static void indexDocsWithFacetsAndTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter,
+ ObjectToIntMap expectedCounts) throws IOException {
+ Random random = random();
+ int numDocs = atLeast(random, 2);
+ FacetFields facetFields = new FacetFields(taxoWriter);
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ addFacets(doc, facetFields, true);
+ addField(doc);
+ indexWriter.addDocument(doc);
+ }
+ indexWriter.commit(); // flush a segment
+ }
+
+ private static void indexDocsWithFacetsAndSomeTerms(IndexWriter indexWriter, TaxonomyWriter taxoWriter,
+ ObjectToIntMap expectedCounts) throws IOException {
+ Random random = random();
+ int numDocs = atLeast(random, 2);
+ FacetFields facetFields = new FacetFields(taxoWriter);
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ boolean hasContent = random.nextBoolean();
+ if (hasContent) {
+ addField(doc);
+ }
+ addFacets(doc, facetFields, hasContent);
+ indexWriter.addDocument(doc);
+ }
+ indexWriter.commit(); // flush a segment
+ }
+
+ // initialize expectedCounts w/ 0 for all categories
+ private static ObjectToIntMap newCounts() {
+ ObjectToIntMap counts = new ObjectToIntMap();
+ counts.put(CP_A, 0);
+ counts.put(CP_B, 0);
+ for (CategoryPath cp : CATEGORIES_A) {
+ counts.put(cp, 0);
+ }
+ for (CategoryPath cp : CATEGORIES_B) {
+ counts.put(cp, 0);
+ }
+ return counts;
+ }
+
+ @BeforeClass
+ public static void beforeClassCountingFacetsCollectorTest() throws Exception {
+ indexDir = newDirectory();
+ taxoDir = newDirectory();
+
+ // create an index which has:
+ // 1. Segment with no categories, but matching results
+ // 2. Segment w/ categories, but no results
+ // 3. Segment w/ categories and results
+ // 4. Segment w/ categories, but only some results
+
+ IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random()));
+ conf.setMergePolicy(NoMergePolicy.COMPOUND_FILES); // prevent merges, so we can control the index segments
+ IndexWriter indexWriter = new IndexWriter(indexDir, conf);
+ TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
+
+ allExpectedCounts = newCounts();
+ termExpectedCounts = newCounts();
+
+ // segment w/ no categories
+ indexDocsNoFacets(indexWriter);
+
+ // segment w/ categories, no content
+ indexDocsWithFacetsNoTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+ // segment w/ categories and content
+ indexDocsWithFacetsAndTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+ // segment w/ categories and some content
+ indexDocsWithFacetsAndSomeTerms(indexWriter, taxoWriter, allExpectedCounts);
+
+ // set num children indexed from each dimension
+ for (CategoryPath cp : CATEGORIES_A) {
+ if (termExpectedCounts.get(cp) > 0) {
+ ++numChildrenIndexedA;
+ }
+ }
+ for (CategoryPath cp : CATEGORIES_B) {
+ if (termExpectedCounts.get(cp) > 0) {
+ ++numChildrenIndexedB;
+ }
+ }
+
+ IOUtils.close(indexWriter, taxoWriter);
+ }
+
+ @Test
+ public void testInvalidValidParams() throws Exception {
+ final CategoryPath dummyCP = new CategoryPath("a");
+ final FacetRequest dummyFR = new CountFacetRequest(dummyCP, 10);
+
+ // only CountFacetRequests are allowed
+ assertNotNull("only CountFacetRequests should be allowed",
+ CountingFacetsCollector.assertParams(new FacetSearchParams(new ScoreFacetRequest(dummyCP, 10))));
+
+ // only depth=1
+ FacetRequest cfr = new CountFacetRequest(dummyCP, 10);
+ cfr.setDepth(2);
+ assertNotNull("only depth 1 should be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(cfr)));
+
+ // no numToLabel
+ cfr = new CountFacetRequest(dummyCP, 10);
+ cfr.setNumLabel(2);
+ assertNotNull("numToLabel should not be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(cfr)));
+
+ FacetIndexingParams fip = new FacetIndexingParams(new CategoryListParams("moo")) {
+ @Override
+ public List getAllCategoryListParams() {
+ return Arrays.asList(new CategoryListParams[] { clParams, clParams });
+ }
+ };
+ assertNotNull("only one CLP should be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(fip, dummyFR)));
+
+ fip = new FacetIndexingParams(new CategoryListParams("moo")) {
+ final CategoryListParams clp = new CategoryListParams() {
+ @Override
+ public IntEncoder createEncoder() {
+ return new VInt8IntEncoder();
+ }
+ };
+ @Override
+ public List getAllCategoryListParams() {
+ return Collections.singletonList(clp);
+ }
+
+ @Override
+ public CategoryListParams getCategoryListParams(CategoryPath category) {
+ return clp;
+ }
+ };
+ assertNotNull("only DGapVIntEncoder should be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(fip, dummyFR)));
+
+ fip = new FacetIndexingParams(new CategoryListParams("moo")) {
+ @Override
+ public int getPartitionSize() {
+ return 2;
+ }
+ };
+ assertNotNull("partitions should be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(fip, dummyFR)));
+
+ fip = new FacetIndexingParams(new CategoryListParams("moo")) {
+ @Override
+ public OrdinalPolicy getOrdinalPolicy() {
+ return OrdinalPolicy.NO_PARENTS;
+ }
+ };
+ assertNotNull("only ALL_PARENTS policy should be allowed", CountingFacetsCollector.assertParams(new FacetSearchParams(fip, dummyFR)));
+ }
+
+ @Test
+ public void testDifferentNumResults() throws Exception {
+ // test the collector w/ FacetRequests and different numResults
+ DirectoryReader indexReader = DirectoryReader.open(indexDir);
+ TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(CP_A, NUM_CHILDREN_CP_A),
+ new CountFacetRequest(CP_B, NUM_CHILDREN_CP_B));
+ FacetsCollector fc = new CountingFacetsCollector(fsp , taxoReader);
+ TermQuery q = new TermQuery(A);
+ searcher.search(q, fc);
+
+ List facetResults = fc.getFacetResults();
+ assertEquals("invalid number of facet results", 2, facetResults.size());
+ for (FacetResult res : facetResults) {
+ FacetResultNode root = res.getFacetResultNode();
+ assertEquals("wrong count for " + root.getLabel(), termExpectedCounts.get(root.getLabel()), (int) root.getValue());
+ assertEquals("invalid residue", 0, (int) root.getResidue());
+ for (FacetResultNode child : root.getSubResults()) {
+ assertEquals("wrong count for " + child.getLabel(), termExpectedCounts.get(child.getLabel()), (int) child.getValue());
+ }
+ }
+
+ IOUtils.close(indexReader, taxoReader);
+ }
+
+ @Test
+ public void testResidue() throws Exception {
+ // test the collector's handling of residue
+ DirectoryReader indexReader = DirectoryReader.open(indexDir);
+ TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ // asking for top 1 is the only way to guarantee there will be a residue
+ // provided that enough children were indexed (see below)
+ FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(CP_A, 1), new CountFacetRequest(CP_B, 1));
+ FacetsCollector fc = new CountingFacetsCollector(fsp , taxoReader);
+ TermQuery q = new TermQuery(A);
+ searcher.search(q, fc);
+
+ List facetResults = fc.getFacetResults();
+ assertEquals("invalid number of facet results", 2, facetResults.size());
+ for (FacetResult res : facetResults) {
+ FacetResultNode root = res.getFacetResultNode();
+ assertEquals("wrong count for " + root.getLabel(), termExpectedCounts.get(root.getLabel()), (int) root.getValue());
+ // make sure randomness didn't pick only one child of root (otherwise there's no residue)
+ int numChildrenIndexed = res.getFacetRequest().categoryPath == CP_A ? numChildrenIndexedA : numChildrenIndexedB;
+ if (numChildrenIndexed > 1) {
+ assertTrue("expected residue", root.getResidue() > 0);
+ }
+ for (FacetResultNode child : root.getSubResults()) {
+ assertEquals("wrong count for " + child.getLabel(), termExpectedCounts.get(child.getLabel()), (int) child.getValue());
+ }
+ }
+
+ IOUtils.close(indexReader, taxoReader);
+ }
+
+ @Test
+ public void testAllCounts() throws Exception {
+ DirectoryReader indexReader = DirectoryReader.open(indexDir);
+ TaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
+ IndexSearcher searcher = new IndexSearcher(indexReader);
+
+ FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(CP_A, NUM_CHILDREN_CP_A),
+ new CountFacetRequest(CP_B, NUM_CHILDREN_CP_B));
+ FacetsCollector fc = new CountingFacetsCollector(fsp , taxoReader);
+ searcher.search(new MatchAllDocsQuery(), fc);
+
+ List facetResults = fc.getFacetResults();
+ assertEquals("invalid number of facet results", 2, facetResults.size());
+ for (FacetResult res : facetResults) {
+ FacetResultNode root = res.getFacetResultNode();
+ assertEquals("wrong count for " + root.getLabel(), allExpectedCounts.get(root.getLabel()), (int) root.getValue());
+ assertEquals("invalid residue", 0, (int) root.getResidue());
+ for (FacetResultNode child : root.getSubResults()) {
+ assertEquals("wrong count for " + child.getLabel(), allExpectedCounts.get(child.getLabel()), (int) child.getValue());
+ }
+ }
+
+ IOUtils.close(indexReader, taxoReader);
+ }
+
+}
Property changes on: lucene/facet/src/test/org/apache/lucene/facet/search/CountingFacetsCollectorTest.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: lucene/facet/src/test/org/apache/lucene/facet/search/SamplingWrapperTest.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/SamplingWrapperTest.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/SamplingWrapperTest.java (working copy)
@@ -29,11 +29,10 @@
public class SamplingWrapperTest extends BaseSampleTestTopK {
@Override
- protected FacetsAccumulator getSamplingAccumulator(Sampler sampler,
- TaxonomyReader taxoReader, IndexReader indexReader,
- FacetSearchParams searchParams) {
- FacetsAccumulator fExtrctr = new StandardFacetsAccumulator(searchParams,
- indexReader, taxoReader);
- return new SamplingWrapper(fExtrctr, sampler);
+ protected FacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader,
+ IndexReader indexReader, FacetSearchParams searchParams) {
+ FacetsAccumulator fa = new StandardFacetsAccumulator(searchParams, indexReader, taxoReader);
+ return new SamplingWrapper(fa, sampler);
}
+
}
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestDemoFacets.java (working copy)
@@ -22,11 +22,11 @@
import java.util.List;
import org.apache.lucene.document.Document;
+import org.apache.lucene.facet.FacetTestUtils;
import org.apache.lucene.facet.index.FacetFields;
import org.apache.lucene.facet.search.params.CountFacetRequest;
import org.apache.lucene.facet.search.params.FacetSearchParams;
import org.apache.lucene.facet.search.results.FacetResult;
-import org.apache.lucene.facet.search.results.FacetResultNode;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
@@ -89,7 +89,7 @@
new CountFacetRequest(new CategoryPath("Author"), 10));
// Aggregatses the facet counts:
- FacetsCollector c = new FacetsCollector(fsp, searcher.getIndexReader(), taxoReader);
+ FacetsCollector c = FacetsCollector.create(fsp, searcher.getIndexReader(), taxoReader);
// MatchAllDocsQuery is for "browsing" (counts facets
// for all non-deleted docs in the index); normally
@@ -101,20 +101,20 @@
List results = c.getFacetResults();
assertEquals(2, results.size());
assertEquals("Publish Date (5)\n 2012 (2)\n 2010 (2)\n 1999 (1)\n",
- toSimpleString(results.get(0)));
+ FacetTestUtils.toSimpleString(results.get(0)));
assertEquals("Author (5)\n Lisa (2)\n Frank (1)\n Susan (1)\n Bob (1)\n",
- toSimpleString(results.get(1)));
+ FacetTestUtils.toSimpleString(results.get(1)));
// Now user drills down on Publish Date/2010:
fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("Author"), 10));
Query q2 = DrillDown.query(fsp, new MatchAllDocsQuery(), new CategoryPath("Publish Date/2010", '/'));
- c = new FacetsCollector(fsp, searcher.getIndexReader(), taxoReader);
+ c = FacetsCollector.create(fsp, searcher.getIndexReader(), taxoReader);
searcher.search(q2, c);
results = c.getFacetResults();
assertEquals(1, results.size());
assertEquals("Author (2)\n Lisa (1)\n Bob (1)\n",
- toSimpleString(results.get(0)));
+ FacetTestUtils.toSimpleString(results.get(0)));
taxoReader.close();
searcher.getIndexReader().close();
@@ -122,16 +122,4 @@
taxoDir.close();
}
- private String toSimpleString(FacetResult fr) {
- StringBuilder sb = new StringBuilder();
- toSimpleString(0, sb, fr.getFacetResultNode(), "");
- return sb.toString();
- }
-
- private void toSimpleString(int depth, StringBuilder sb, FacetResultNode node, String indent) {
- sb.append(indent + node.getLabel().components[depth] + " (" + (int) node.getValue() + ")\n");
- for(FacetResultNode childNode : node.getSubResults()) {
- toSimpleString(depth+1, sb, childNode, indent + " ");
- }
- }
}
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java (working copy)
@@ -71,7 +71,7 @@
DirectoryReader r = DirectoryReader.open(indexDir);
DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir);
- FacetsCollector fc = new FacetsCollector(sParams, r, taxo);
+ FacetsCollector fc = FacetsCollector.create(sParams, r, taxo);
TopScoreDocCollector topDocs = TopScoreDocCollector.create(10, false);
new IndexSearcher(r).search(new MatchAllDocsQuery(), MultiCollector.wrap(fc, topDocs));
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (working copy)
@@ -334,7 +334,7 @@
FacetSearchParams facetSearchParams = new FacetSearchParams(facetRequests, iParams);
// perform documents search and facets accumulation
- FacetsCollector facetsCollector = new FacetsCollector(facetSearchParams, ir, tr);
+ FacetsCollector facetsCollector = FacetsCollector.create(facetSearchParams, ir, tr);
searcher.search(q, MultiCollector.wrap(topDocsCollector, facetsCollector));
return facetsCollector;
}
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestSameRequestAccumulation.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestSameRequestAccumulation.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestSameRequestAccumulation.java (working copy)
@@ -44,7 +44,7 @@
final CountFacetRequest facetRequest = new CountFacetRequest(new CategoryPath("root"), 10);
FacetSearchParams fsp = new FacetSearchParams(facetRequest);
- FacetsCollector fc = new FacetsCollector(fsp, indexReader, taxoReader);
+ FacetsCollector fc = FacetsCollector.create(fsp, indexReader, taxoReader);
searcher.search(new MatchAllDocsQuery(), fc);
final String expected = fc.getFacetResults().get(0).toString();
@@ -53,9 +53,9 @@
fsp = new FacetSearchParams(facetRequest, facetRequest, new CountFacetRequest(new CategoryPath("root"), 10));
// make sure the search params holds 3 requests now
- assertEquals(3, fsp.getFacetRequests().size());
+ assertEquals(3, fsp.facetRequests.size());
- fc = new FacetsCollector(fsp, indexReader, taxoReader);
+ fc = FacetsCollector.create(fsp, indexReader, taxoReader);
searcher.search(new MatchAllDocsQuery(), fc);
List actual = fc.getFacetResults();
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestStandardFacetsAccumulator.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestStandardFacetsAccumulator.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestStandardFacetsAccumulator.java (working copy)
@@ -1,7 +1,6 @@
package org.apache.lucene.facet.search;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -102,16 +101,14 @@
// search for "f:a", only segments 1 and 3 should match results
Query q = new TermQuery(new Term("f", "a"));
- ArrayList requests = new ArrayList(1);
- CountFacetRequest countNoComplements = new CountFacetRequest(new CategoryPath("A"), 10) {
+ FacetRequest countNoComplements = new CountFacetRequest(new CategoryPath("A"), 10) {
@Override
public boolean supportsComplements() {
return false; // disable complements
}
};
- requests.add(countNoComplements);
- FacetSearchParams fsp = new FacetSearchParams(requests, fip);
- FacetsCollector fc = new FacetsCollector(fsp , indexReader, taxoReader);
+ FacetSearchParams fsp = new FacetSearchParams(fip, countNoComplements);
+ FacetsCollector fc = FacetsCollector.create(fsp , indexReader, taxoReader);
indexSearcher.search(q, fc);
List results = fc.getFacetResults();
assertEquals("received too many facet results", 1, results.size());
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java (working copy)
@@ -165,7 +165,7 @@
facetRequests.add(cfrb20);
FacetSearchParams facetSearchParams = new FacetSearchParams(facetRequests, iParams);
- FacetArrays facetArrays = new FacetArrays(PartitionsUtils.partitionSize(facetSearchParams.getFacetIndexingParams(), tr));
+ FacetArrays facetArrays = new FacetArrays(PartitionsUtils.partitionSize(facetSearchParams.indexingParams, tr));
FacetsAccumulator fctExtrctr = new StandardFacetsAccumulator(facetSearchParams, is.getIndexReader(), tr, facetArrays);
fctExtrctr.setComplementThreshold(FacetsAccumulator.DISABLE_COMPLEMENT);
long start = System.currentTimeMillis();
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java (working copy)
@@ -89,7 +89,7 @@
// do different facet counts and compare to control
FacetSearchParams sParams = getFacetSearchParams(facetRequests, getFacetIndexingParams(partitionSize));
- FacetsCollector fc = new FacetsCollector(sParams, indexReader, taxoReader) {
+ FacetsCollector fc = new StandardFacetsCollector(sParams, indexReader, taxoReader) {
@Override
protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
FacetsAccumulator fa = new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
@@ -159,10 +159,10 @@
// do different facet counts and compare to control
CategoryPath path = new CategoryPath("a", "b");
- FacetSearchParams sParams = getFacetSearchParams(
- getFacetIndexingParams(partitionSize), new CountFacetRequest(path, Integer.MAX_VALUE));
+ FacetSearchParams sParams = getFacetSearchParams(getFacetIndexingParams(partitionSize),
+ new CountFacetRequest(path, Integer.MAX_VALUE));
- FacetsCollector fc = new FacetsCollector(sParams, indexReader, taxoReader) {
+ FacetsCollector fc = new StandardFacetsCollector(sParams, indexReader, taxoReader) {
@Override
protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
FacetsAccumulator fa = new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
@@ -188,7 +188,7 @@
FacetSearchParams sParams2 = getFacetSearchParams(
getFacetIndexingParams(partitionSize), new CountFacetRequest(path, Integer.MAX_VALUE));
- FacetsCollector fc2 = new FacetsCollector(sParams2, indexReader, taxoReader) {
+ FacetsCollector fc2 = new StandardFacetsCollector(sParams2, indexReader, taxoReader) {
@Override
protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams, IndexReader indexReader, TaxonomyReader taxonomyReader) {
FacetsAccumulator fa = new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
@@ -226,7 +226,7 @@
getFacetIndexingParams(partitionSize),
new CountFacetRequest(path, 10));
- FacetsCollector fc = new FacetsCollector(sParams, indexReader, taxoReader);
+ FacetsCollector fc = FacetsCollector.create(sParams, indexReader, taxoReader);
searcher.search(new MatchAllDocsQuery(), fc);
Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandlerRandom.java (working copy)
@@ -4,16 +4,15 @@
import java.util.HashMap;
import java.util.List;
+import org.apache.lucene.facet.search.params.FacetSearchParams;
+import org.apache.lucene.facet.search.results.FacetResult;
+import org.apache.lucene.facet.search.results.FacetResultNode;
+import org.apache.lucene.facet.taxonomy.TaxonomyReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.junit.Test;
-import org.apache.lucene.facet.search.params.FacetSearchParams;
-import org.apache.lucene.facet.search.results.FacetResult;
-import org.apache.lucene.facet.search.results.FacetResultNode;
-import org.apache.lucene.facet.taxonomy.TaxonomyReader;
-
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -37,7 +36,7 @@
throws IOException {
Query q = new MatchAllDocsQuery();
FacetSearchParams facetSearchParams = searchParamsWithRequests(numResults, partitionSize);
- FacetsCollector fc = new FacetsCollector(facetSearchParams, indexReader, taxoReader) {
+ FacetsCollector fc = new StandardFacetsCollector(facetSearchParams, indexReader, taxoReader) {
@Override
protected FacetsAccumulator initFacetsAccumulator(
FacetSearchParams facetSearchParams, IndexReader indexReader,
Index: lucene/facet/src/test/org/apache/lucene/facet/search/associations/AssociationsFacetRequestTest.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/associations/AssociationsFacetRequestTest.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/associations/AssociationsFacetRequestTest.java (working copy)
@@ -110,7 +110,7 @@
Query q = new MatchAllDocsQuery();
- FacetsCollector fc = new FacetsCollector(fsp, reader, taxo);
+ FacetsCollector fc = FacetsCollector.create(fsp, reader, taxo);
IndexSearcher searcher = newSearcher(reader);
searcher.search(q, fc);
@@ -135,7 +135,7 @@
Query q = new MatchAllDocsQuery();
- FacetsCollector fc = new FacetsCollector(fsp, reader, taxo);
+ FacetsCollector fc = FacetsCollector.create(fsp, reader, taxo);
IndexSearcher searcher = newSearcher(reader);
searcher.search(q, fc);
@@ -165,7 +165,7 @@
Query q = new MatchAllDocsQuery();
- FacetsCollector fc = new FacetsCollector(fsp, reader, taxo);
+ FacetsCollector fc = FacetsCollector.create(fsp, reader, taxo);
IndexSearcher searcher = newSearcher(reader);
searcher.search(q, fc);
Index: lucene/facet/src/test/org/apache/lucene/facet/search/sampling/BaseSampleTestTopK.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/sampling/BaseSampleTestTopK.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/sampling/BaseSampleTestTopK.java (working copy)
@@ -3,22 +3,22 @@
import java.util.List;
import java.util.Random;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermQuery;
-
-import org.apache.lucene.search.MultiCollector;
import org.apache.lucene.facet.search.BaseTestTopK;
import org.apache.lucene.facet.search.FacetsAccumulator;
import org.apache.lucene.facet.search.FacetsCollector;
import org.apache.lucene.facet.search.ScoredDocIDs;
import org.apache.lucene.facet.search.ScoredDocIdCollector;
+import org.apache.lucene.facet.search.StandardFacetsCollector;
import org.apache.lucene.facet.search.params.FacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest.ResultMode;
import org.apache.lucene.facet.search.params.FacetSearchParams;
import org.apache.lucene.facet.search.results.FacetResult;
import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MultiCollector;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -48,7 +48,7 @@
@Override
protected FacetSearchParams searchParamsWithRequests(int numResults, int partitionSize) {
FacetSearchParams res = super.searchParamsWithRequests(numResults, partitionSize);
- for (FacetRequest req : res.getFacetRequests()) {
+ for (FacetRequest req : res.facetRequests) {
// randomize the way we aggregate results
if (random().nextBoolean()) {
req.setResultMode(ResultMode.GLOBAL_FLAT);
@@ -78,7 +78,7 @@
ScoredDocIdCollector docCollector = ScoredDocIdCollector.create(indexReader.maxDoc(), false);
FacetSearchParams expectedSearchParams = searchParamsWithRequests(K, partitionSize);
- FacetsCollector fc = new FacetsCollector(expectedSearchParams, indexReader, taxoReader);
+ FacetsCollector fc = FacetsCollector.create(expectedSearchParams, indexReader, taxoReader);
searcher.search(q, MultiCollector.wrap(docCollector, fc));
@@ -97,7 +97,7 @@
assertSampling(expectedResults, q, sampler, samplingSearchParams, true);
break; // succeeded
- } catch (NotSameResultError e) {
+ } catch (AssertionError e) {
if (nTrial >= RETRIES - 1) {
throw e; // no more retries allowed, must fail
}
@@ -120,7 +120,7 @@
private FacetsCollector samplingCollector(final boolean complement, final Sampler sampler,
FacetSearchParams samplingSearchParams) {
- FacetsCollector samplingFC = new FacetsCollector(samplingSearchParams, indexReader, taxoReader) {
+ FacetsCollector samplingFC = new StandardFacetsCollector(samplingSearchParams, indexReader, taxoReader) {
@Override
protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams, IndexReader indexReader,
TaxonomyReader taxonomyReader) {
Index: lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java
===================================================================
--- lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java (revision 1434923)
+++ lucene/facet/src/test/org/apache/lucene/facet/search/sampling/OversampleWithDepthTest.java (working copy)
@@ -8,6 +8,7 @@
import org.apache.lucene.facet.index.FacetFields;
import org.apache.lucene.facet.search.FacetsAccumulator;
import org.apache.lucene.facet.search.FacetsCollector;
+import org.apache.lucene.facet.search.StandardFacetsCollector;
import org.apache.lucene.facet.search.params.CountFacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest;
import org.apache.lucene.facet.search.params.FacetRequest.ResultMode;
@@ -111,11 +112,10 @@
}
/** search reader r*/
- private FacetResult searchWithFacets(IndexReader r,
- TaxonomyReader tr, FacetSearchParams fsp, final SamplingParams params)
- throws IOException {
+ private FacetResult searchWithFacets(IndexReader r, TaxonomyReader tr, FacetSearchParams fsp,
+ final SamplingParams params) throws IOException {
// a FacetsCollector with a sampling accumulator
- FacetsCollector fcWithSampling = new FacetsCollector(fsp, r, tr) {
+ FacetsCollector fcWithSampling = new StandardFacetsCollector(fsp, r, tr) {
@Override
protected FacetsAccumulator initFacetsAccumulator(FacetSearchParams facetSearchParams, IndexReader indexReader,
TaxonomyReader taxonomyReader) {