mirror of https://github.com/apache/lucene.git
LUCENE-4885: FacetsAccumulator did not set the correct value for FacetResult.numValidDescendants
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1466629 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8e6108528b
commit
7e257c79fc
|
@ -254,6 +254,9 @@ Bug Fixes
|
||||||
* LUCENE-4880: Fix MemoryIndex to consume empty terms from the tokenstream consistent
|
* LUCENE-4880: Fix MemoryIndex to consume empty terms from the tokenstream consistent
|
||||||
with IndexWriter. Previously it discarded them. (Timothy Allison via Robert Muir)
|
with IndexWriter. Previously it discarded them. (Timothy Allison via Robert Muir)
|
||||||
|
|
||||||
|
* LUCENE-4885: FacetsAccumulator did not set the correct value for
|
||||||
|
FacetResult.numValidDescendants. (Mike McCandless, Shai Erera)
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
|
|
||||||
* LUCENE-4841: Added example SimpleSortedSetFacetsExample to show how
|
* LUCENE-4841: Added example SimpleSortedSetFacetsExample to show how
|
||||||
|
|
|
@ -46,7 +46,7 @@ public abstract class DepthOneFacetResultsHandler extends FacetResultsHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FacetResultNode getSentinelObject() {
|
protected FacetResultNode getSentinelObject() {
|
||||||
return new FacetResultNode();
|
return new FacetResultNode(TaxonomyReader.INVALID_ORDINAL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,7 +80,8 @@ public abstract class DepthOneFacetResultsHandler extends FacetResultsHandler {
|
||||||
* Add the siblings of {@code ordinal} to the given {@link PriorityQueue}. The
|
* Add the siblings of {@code ordinal} to the given {@link PriorityQueue}. The
|
||||||
* given {@link PriorityQueue} is already filled with sentinel objects, so
|
* given {@link PriorityQueue} is already filled with sentinel objects, so
|
||||||
* implementations are encouraged to use {@link PriorityQueue#top()} and
|
* implementations are encouraged to use {@link PriorityQueue#top()} and
|
||||||
* {@link PriorityQueue#updateTop()} for best performance.
|
* {@link PriorityQueue#updateTop()} for best performance. Returns the total
|
||||||
|
* number of siblings.
|
||||||
*/
|
*/
|
||||||
protected abstract int addSiblings(int ordinal, int[] siblings, PriorityQueue<FacetResultNode> pq);
|
protected abstract int addSiblings(int ordinal, int[] siblings, PriorityQueue<FacetResultNode> pq);
|
||||||
|
|
||||||
|
@ -92,10 +93,8 @@ public abstract class DepthOneFacetResultsHandler extends FacetResultsHandler {
|
||||||
|
|
||||||
int rootOrd = taxonomyReader.getOrdinal(facetRequest.categoryPath);
|
int rootOrd = taxonomyReader.getOrdinal(facetRequest.categoryPath);
|
||||||
|
|
||||||
FacetResultNode root = new FacetResultNode();
|
FacetResultNode root = new FacetResultNode(rootOrd, valueOf(rootOrd));
|
||||||
root.ordinal = rootOrd;
|
|
||||||
root.label = facetRequest.categoryPath;
|
root.label = facetRequest.categoryPath;
|
||||||
root.value = valueOf(rootOrd);
|
|
||||||
if (facetRequest.numResults > taxonomyReader.getSize()) {
|
if (facetRequest.numResults > taxonomyReader.getSize()) {
|
||||||
// specialize this case, user is interested in all available results
|
// specialize this case, user is interested in all available results
|
||||||
ArrayList<FacetResultNode> nodes = new ArrayList<FacetResultNode>();
|
ArrayList<FacetResultNode> nodes = new ArrayList<FacetResultNode>();
|
||||||
|
@ -118,11 +117,11 @@ public abstract class DepthOneFacetResultsHandler extends FacetResultsHandler {
|
||||||
|
|
||||||
// since we use sentinel objects, we cannot reuse PQ. but that's ok because it's not big
|
// since we use sentinel objects, we cannot reuse PQ. but that's ok because it's not big
|
||||||
PriorityQueue<FacetResultNode> pq = new FacetResultNodeQueue(facetRequest.numResults, true);
|
PriorityQueue<FacetResultNode> pq = new FacetResultNodeQueue(facetRequest.numResults, true);
|
||||||
int numResults = addSiblings(children[rootOrd], siblings, pq);
|
int numSiblings = addSiblings(children[rootOrd], siblings, pq);
|
||||||
|
|
||||||
// pop() the least (sentinel) elements
|
// pop() the least (sentinel) elements
|
||||||
int pqsize = pq.size();
|
int pqsize = pq.size();
|
||||||
int size = numResults < pqsize ? numResults : pqsize;
|
int size = numSiblings < pqsize ? numSiblings : pqsize;
|
||||||
for (int i = pqsize - size; i > 0; i--) { pq.pop(); }
|
for (int i = pqsize - size; i > 0; i--) { pq.pop(); }
|
||||||
|
|
||||||
// create the FacetResultNodes.
|
// create the FacetResultNodes.
|
||||||
|
@ -133,7 +132,7 @@ public abstract class DepthOneFacetResultsHandler extends FacetResultsHandler {
|
||||||
subResults[i] = node;
|
subResults[i] = node;
|
||||||
}
|
}
|
||||||
root.subResults = Arrays.asList(subResults);
|
root.subResults = Arrays.asList(subResults);
|
||||||
return new FacetResult(facetRequest, root, size);
|
return new FacetResult(facetRequest, root, numSiblings);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,19 +40,15 @@ public class FacetResult {
|
||||||
* @see FacetRequest#categoryPath
|
* @see FacetRequest#categoryPath
|
||||||
*/
|
*/
|
||||||
public final FacetResultNode getFacetResultNode() {
|
public final FacetResultNode getFacetResultNode() {
|
||||||
return this.rootNode;
|
return rootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of descendants of {@link #getFacetResultNode() root facet result
|
* Number of descendants of {@link #getFacetResultNode() root facet result
|
||||||
* node}, up till the requested depth. Typically -- have value != 0. This
|
* node}, up till the requested depth.
|
||||||
* number does not include the root node.
|
|
||||||
*
|
|
||||||
* @see #getFacetRequest()
|
|
||||||
* @see FacetRequest#getDepth()
|
|
||||||
*/
|
*/
|
||||||
public final int getNumValidDescendants() {
|
public final int getNumValidDescendants() {
|
||||||
return this.numValidDescendants;
|
return numValidDescendants;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -67,10 +67,6 @@ public class FacetResultNode {
|
||||||
*/
|
*/
|
||||||
public List<FacetResultNode> subResults = EMPTY_SUB_RESULTS;
|
public List<FacetResultNode> subResults = EMPTY_SUB_RESULTS;
|
||||||
|
|
||||||
public FacetResultNode() {
|
|
||||||
// empty constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
public FacetResultNode(int ordinal, double value) {
|
public FacetResultNode(int ordinal, double value) {
|
||||||
this.ordinal = ordinal;
|
this.ordinal = ordinal;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -81,11 +81,10 @@ public class FacetsAccumulator {
|
||||||
return new FacetsAccumulator(fsp, indexReader, taxoReader);
|
return new FacetsAccumulator(fsp, indexReader, taxoReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FacetResult emptyResult(int ordinal, FacetRequest fr) {
|
/** Returns an empty {@link FacetResult}. */
|
||||||
FacetResultNode root = new FacetResultNode();
|
protected static FacetResult emptyResult(int ordinal, FacetRequest fr) {
|
||||||
root.ordinal = ordinal;
|
FacetResultNode root = new FacetResultNode(ordinal, 0);
|
||||||
root.label = fr.categoryPath;
|
root.label = fr.categoryPath;
|
||||||
root.value = 0;
|
|
||||||
return new FacetResult(fr, root, 0);
|
return new FacetResult(fr, root, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,18 +43,19 @@ public final class FloatFacetResultsHandler extends DepthOneFacetResultsHandler
|
||||||
return values[ordinal];
|
return values[ordinal];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final int addSiblings(int ordinal, int[] siblings, PriorityQueue<FacetResultNode> pq) {
|
protected final int addSiblings(int ordinal, int[] siblings, PriorityQueue<FacetResultNode> pq) {
|
||||||
FacetResultNode top = pq.top();
|
FacetResultNode top = pq.top();
|
||||||
int numResults = 0;
|
int numResults = 0;
|
||||||
while (ordinal != TaxonomyReader.INVALID_ORDINAL) {
|
while (ordinal != TaxonomyReader.INVALID_ORDINAL) {
|
||||||
float value = values[ordinal];
|
float value = values[ordinal];
|
||||||
if (value > top.value) {
|
if (value > 0.0f) {
|
||||||
top.value = value;
|
|
||||||
top.ordinal = ordinal;
|
|
||||||
top = pq.updateTop();
|
|
||||||
++numResults;
|
++numResults;
|
||||||
|
if (value > top.value) {
|
||||||
|
top.value = value;
|
||||||
|
top.ordinal = ordinal;
|
||||||
|
top = pq.updateTop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ordinal = siblings[ordinal];
|
ordinal = siblings[ordinal];
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,13 @@ public final class IntFacetResultsHandler extends DepthOneFacetResultsHandler {
|
||||||
int numResults = 0;
|
int numResults = 0;
|
||||||
while (ordinal != TaxonomyReader.INVALID_ORDINAL) {
|
while (ordinal != TaxonomyReader.INVALID_ORDINAL) {
|
||||||
int value = values[ordinal];
|
int value = values[ordinal];
|
||||||
if (value > top.value) {
|
if (value > 0) {
|
||||||
top.value = value;
|
|
||||||
top.ordinal = ordinal;
|
|
||||||
top = pq.updateTop();
|
|
||||||
++numResults;
|
++numResults;
|
||||||
|
if (value > top.value) {
|
||||||
|
top.value = value;
|
||||||
|
top.ordinal = ordinal;
|
||||||
|
top = pq.updateTop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ordinal = siblings[ordinal];
|
ordinal = siblings[ordinal];
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,11 +198,7 @@ public class StandardFacetsAccumulator extends FacetsAccumulator {
|
||||||
IntermediateFacetResult tmpResult = fr2tmpRes.get(fr);
|
IntermediateFacetResult tmpResult = fr2tmpRes.get(fr);
|
||||||
if (tmpResult == null) {
|
if (tmpResult == null) {
|
||||||
// Add empty FacetResult:
|
// Add empty FacetResult:
|
||||||
FacetResultNode root = new FacetResultNode();
|
res.add(emptyResult(taxonomyReader.getOrdinal(fr.categoryPath), fr));
|
||||||
root.ordinal = TaxonomyReader.INVALID_ORDINAL;
|
|
||||||
root.label = fr.categoryPath;
|
|
||||||
root.value = 0;
|
|
||||||
res.add(new FacetResult(fr, root, 0));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FacetResult facetRes = frHndlr.renderFacetResult(tmpResult);
|
FacetResult facetRes = frHndlr.renderFacetResult(tmpResult);
|
||||||
|
|
|
@ -256,7 +256,6 @@ public class TopKFacetResultsHandler extends PartitionsFacetResultsHandler {
|
||||||
* Create a Facet Result.
|
* Create a Facet Result.
|
||||||
* @param facetRequest Request for which this result was obtained.
|
* @param facetRequest Request for which this result was obtained.
|
||||||
* @param facetResultNode top result node for this facet result.
|
* @param facetResultNode top result node for this facet result.
|
||||||
* @param totalFacets - number of children of the targetFacet, up till the requested depth.
|
|
||||||
*/
|
*/
|
||||||
TopKFacetResult(FacetRequest facetRequest, FacetResultNode facetResultNode, int totalFacets) {
|
TopKFacetResult(FacetRequest facetRequest, FacetResultNode facetResultNode, int totalFacets) {
|
||||||
super(facetRequest, facetResultNode, totalFacets);
|
super(facetRequest, facetResultNode, totalFacets);
|
||||||
|
|
|
@ -706,8 +706,7 @@ public class TopKInEachNodeHandler extends PartitionsFacetResultsHandler {
|
||||||
value = tmp.rootNodeValue;
|
value = tmp.rootNodeValue;
|
||||||
}
|
}
|
||||||
FacetResultNode root = generateNode(ordinal, value, tmp.mapToAACOs);
|
FacetResultNode root = generateNode(ordinal, value, tmp.mapToAACOs);
|
||||||
return new FacetResult (tmp.facetRequest, root, tmp.totalNumOfFacetsConsidered);
|
return new FacetResult(tmp.facetRequest, root, tmp.totalNumOfFacetsConsidered);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FacetResultNode generateNode(int ordinal, double val, IntToObjectMap<AACO> mapToAACOs) {
|
private FacetResultNode generateNode(int ordinal, double val, IntToObjectMap<AACO> mapToAACOs) {
|
||||||
|
|
|
@ -107,7 +107,6 @@ public class SortedSetDocValuesAccumulator extends FacetsAccumulator {
|
||||||
|
|
||||||
if (matchingDocs.totalHits < numSegOrds/10) {
|
if (matchingDocs.totalHits < numSegOrds/10) {
|
||||||
// Remap every ord to global ord as we iterate:
|
// Remap every ord to global ord as we iterate:
|
||||||
final int[] segCounts = new int[numSegOrds];
|
|
||||||
int doc = 0;
|
int doc = 0;
|
||||||
while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
|
while (doc < maxDoc && (doc = matchingDocs.bits.nextSetBit(doc)) != -1) {
|
||||||
segValues.setDocument(doc);
|
segValues.setDocument(doc);
|
||||||
|
@ -259,22 +258,26 @@ public class SortedSetDocValuesAccumulator extends FacetsAccumulator {
|
||||||
|
|
||||||
//System.out.println("collect");
|
//System.out.println("collect");
|
||||||
int dimCount = 0;
|
int dimCount = 0;
|
||||||
|
int childCount = 0;
|
||||||
FacetResultNode reuse = null;
|
FacetResultNode reuse = null;
|
||||||
for(int ord=ordRange.start; ord<=ordRange.end; ord++) {
|
for(int ord=ordRange.start; ord<=ordRange.end; ord++) {
|
||||||
//System.out.println(" ord=" + ord + " count= "+ counts[ord] + " bottomCount=" + bottomCount);
|
//System.out.println(" ord=" + ord + " count= "+ counts[ord] + " bottomCount=" + bottomCount);
|
||||||
if (counts[ord] > bottomCount) {
|
if (counts[ord] > 0) {
|
||||||
dimCount += counts[ord];
|
childCount++;
|
||||||
//System.out.println(" keep");
|
if (counts[ord] > bottomCount) {
|
||||||
if (reuse == null) {
|
dimCount += counts[ord];
|
||||||
reuse = new FacetResultNode(ord, counts[ord]);
|
//System.out.println(" keep");
|
||||||
} else {
|
if (reuse == null) {
|
||||||
reuse.ordinal = ord;
|
reuse = new FacetResultNode(ord, counts[ord]);
|
||||||
reuse.value = counts[ord];
|
} else {
|
||||||
}
|
reuse.ordinal = ord;
|
||||||
reuse = q.insertWithOverflow(reuse);
|
reuse.value = counts[ord];
|
||||||
if (q.size() == request.numResults) {
|
}
|
||||||
bottomCount = (int) q.top().value;
|
reuse = q.insertWithOverflow(reuse);
|
||||||
//System.out.println(" new bottom=" + bottomCount);
|
if (q.size() == request.numResults) {
|
||||||
|
bottomCount = (int) q.top().value;
|
||||||
|
//System.out.println(" new bottom=" + bottomCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +298,7 @@ public class SortedSetDocValuesAccumulator extends FacetsAccumulator {
|
||||||
}
|
}
|
||||||
rootNode.subResults = Arrays.asList(childNodes);
|
rootNode.subResults = Arrays.asList(childNodes);
|
||||||
|
|
||||||
results.add(new FacetResult(request, rootNode, childNodes.length));
|
results.add(new FacetResult(request, rootNode, childCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
|
@ -150,10 +150,13 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
// Publish Date is only drill-down, and Lisa published
|
// Publish Date is only drill-down, and Lisa published
|
||||||
// one in 2012 and one in 2010:
|
// one in 2012 and one in 2010:
|
||||||
assertEquals("Publish Date: 2012=1 2010=1", toString(r.facetResults.get(0)));
|
assertEquals("Publish Date: 2012=1 2010=1", toString(r.facetResults.get(0)));
|
||||||
|
assertEquals(2, r.facetResults.get(0).getNumValidDescendants());
|
||||||
|
|
||||||
// Author is drill-sideways + drill-down: Lisa
|
// Author is drill-sideways + drill-down: Lisa
|
||||||
// (drill-down) published twice, and Frank/Susan/Bob
|
// (drill-down) published twice, and Frank/Susan/Bob
|
||||||
// published once:
|
// published once:
|
||||||
assertEquals("Author: Lisa=2 Frank=1 Susan=1 Bob=1", toString(r.facetResults.get(1)));
|
assertEquals("Author: Lisa=2 Frank=1 Susan=1 Bob=1", toString(r.facetResults.get(1)));
|
||||||
|
assertEquals(4, r.facetResults.get(1).getNumValidDescendants());
|
||||||
|
|
||||||
// Another simple case: drill-down on on single fields
|
// Another simple case: drill-down on on single fields
|
||||||
// but OR of two values
|
// but OR of two values
|
||||||
|
@ -766,6 +769,7 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
ds = new DrillSideways(s, tr);
|
ds = new DrillSideways(s, tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve all facets:
|
||||||
DrillSidewaysResult actual = ds.search(ddq, filter, null, numDocs, sort, true, true, fsp);
|
DrillSidewaysResult actual = ds.search(ddq, filter, null, numDocs, sort, true, true, fsp);
|
||||||
|
|
||||||
TopDocs hits = s.search(baseQuery, numDocs);
|
TopDocs hits = s.search(baseQuery, numDocs);
|
||||||
|
@ -773,9 +777,12 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
for(ScoreDoc sd : hits.scoreDocs) {
|
for(ScoreDoc sd : hits.scoreDocs) {
|
||||||
scores.put(s.doc(sd.doc).get("id"), sd.score);
|
scores.put(s.doc(sd.doc).get("id"), sd.score);
|
||||||
}
|
}
|
||||||
|
if (VERBOSE) {
|
||||||
|
System.out.println(" verify all facets");
|
||||||
|
}
|
||||||
verifyEquals(requests, dimValues, s, expected, actual, scores, -1, doUseDV);
|
verifyEquals(requests, dimValues, s, expected, actual, scores, -1, doUseDV);
|
||||||
|
|
||||||
// Make sure topN works:
|
// Retrieve topN facets:
|
||||||
int topN = _TestUtil.nextInt(random(), 1, 20);
|
int topN = _TestUtil.nextInt(random(), 1, 20);
|
||||||
|
|
||||||
List<FacetRequest> newRequests = new ArrayList<FacetRequest>();
|
List<FacetRequest> newRequests = new ArrayList<FacetRequest>();
|
||||||
|
@ -784,6 +791,9 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
}
|
}
|
||||||
fsp = new FacetSearchParams(newRequests);
|
fsp = new FacetSearchParams(newRequests);
|
||||||
actual = ds.search(ddq, filter, null, numDocs, sort, true, true, fsp);
|
actual = ds.search(ddq, filter, null, numDocs, sort, true, true, fsp);
|
||||||
|
if (VERBOSE) {
|
||||||
|
System.out.println(" verify topN=" + topN);
|
||||||
|
}
|
||||||
verifyEquals(newRequests, dimValues, s, expected, actual, scores, topN, doUseDV);
|
verifyEquals(newRequests, dimValues, s, expected, actual, scores, topN, doUseDV);
|
||||||
|
|
||||||
// Make sure drill down doesn't change score:
|
// Make sure drill down doesn't change score:
|
||||||
|
@ -834,6 +844,7 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
private static class SimpleFacetResult {
|
private static class SimpleFacetResult {
|
||||||
List<Doc> hits;
|
List<Doc> hits;
|
||||||
int[][] counts;
|
int[][] counts;
|
||||||
|
int[] uniqueCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] getTopNOrds(final int[] counts, final String[] values, int topN) {
|
private int[] getTopNOrds(final int[] counts, final String[] values, int topN) {
|
||||||
|
@ -985,13 +996,21 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
SimpleFacetResult res = new SimpleFacetResult();
|
SimpleFacetResult res = new SimpleFacetResult();
|
||||||
res.hits = hits;
|
res.hits = hits;
|
||||||
res.counts = new int[numDims][];
|
res.counts = new int[numDims][];
|
||||||
for(int i=0;i<requests.size();i++) {
|
res.uniqueCounts = new int[numDims];
|
||||||
|
for (int i = 0; i < requests.size(); i++) {
|
||||||
int dim = Integer.parseInt(requests.get(i).categoryPath.components[0].substring(3));
|
int dim = Integer.parseInt(requests.get(i).categoryPath.components[0].substring(3));
|
||||||
if (drillDowns[dim] != null) {
|
if (drillDowns[dim] != null) {
|
||||||
res.counts[dim] = drillSidewaysCounts[dim].counts[dim];
|
res.counts[dim] = drillSidewaysCounts[dim].counts[dim];
|
||||||
} else {
|
} else {
|
||||||
res.counts[dim] = drillDownCounts.counts[dim];
|
res.counts[dim] = drillDownCounts.counts[dim];
|
||||||
}
|
}
|
||||||
|
int uniqueCount = 0;
|
||||||
|
for (int j = 0; j < res.counts[dim].length; j++) {
|
||||||
|
if (res.counts[dim][j] != 0) {
|
||||||
|
uniqueCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res.uniqueCounts[dim] = uniqueCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -1107,6 +1126,8 @@ public class TestDrillSideways extends FacetTestCase {
|
||||||
}
|
}
|
||||||
assertEquals(setCount, actualValues.size());
|
assertEquals(setCount, actualValues.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertEquals("dim=" + dim, expected.uniqueCounts[dim], fr.getNumValidDescendants());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.apache.lucene.facet.params.CategoryListParams;
|
||||||
import org.apache.lucene.facet.params.FacetIndexingParams;
|
import org.apache.lucene.facet.params.FacetIndexingParams;
|
||||||
import org.apache.lucene.facet.params.FacetSearchParams;
|
import org.apache.lucene.facet.params.FacetSearchParams;
|
||||||
import org.apache.lucene.facet.params.PerDimensionIndexingParams;
|
import org.apache.lucene.facet.params.PerDimensionIndexingParams;
|
||||||
|
import org.apache.lucene.facet.search.FacetRequest.ResultMode;
|
||||||
import org.apache.lucene.facet.taxonomy.CategoryPath;
|
import org.apache.lucene.facet.taxonomy.CategoryPath;
|
||||||
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
|
import org.apache.lucene.facet.taxonomy.TaxonomyWriter;
|
||||||
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
|
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
|
||||||
|
@ -349,4 +350,39 @@ public class TestFacetsCollector extends FacetTestCase {
|
||||||
IOUtils.close(taxo, taxoDir, r, indexDir);
|
IOUtils.close(taxo, taxoDir, r, indexDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNumValidDescendants() throws Exception {
|
||||||
|
// LUCENE-4885: FacetResult.numValidDescendants was not set properly by FacetsAccumulator
|
||||||
|
Directory indexDir = newDirectory();
|
||||||
|
Directory taxoDir = newDirectory();
|
||||||
|
|
||||||
|
TaxonomyWriter taxonomyWriter = new DirectoryTaxonomyWriter(taxoDir);
|
||||||
|
IndexWriter iw = new IndexWriter(indexDir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())));
|
||||||
|
|
||||||
|
FacetFields facetFields = new FacetFields(taxonomyWriter);
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
Document doc = new Document();
|
||||||
|
facetFields.addFields(doc, Arrays.asList(new CategoryPath("a", Integer.toString(i))));
|
||||||
|
iw.addDocument(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
taxonomyWriter.close();
|
||||||
|
iw.close();
|
||||||
|
|
||||||
|
DirectoryReader r = DirectoryReader.open(indexDir);
|
||||||
|
DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir);
|
||||||
|
|
||||||
|
CountFacetRequest cfr = new CountFacetRequest(new CategoryPath("a"), 2);
|
||||||
|
cfr.setResultMode(random().nextBoolean() ? ResultMode.GLOBAL_FLAT : ResultMode.PER_NODE_IN_TREE);
|
||||||
|
FacetSearchParams fsp = new FacetSearchParams(cfr);
|
||||||
|
final FacetsAccumulator fa = random().nextBoolean() ? new FacetsAccumulator(fsp, r, taxo) : new StandardFacetsAccumulator(fsp, r, taxo);
|
||||||
|
FacetsCollector fc = FacetsCollector.create(fa);
|
||||||
|
new IndexSearcher(r).search(new MatchAllDocsQuery(), fc);
|
||||||
|
|
||||||
|
FacetResult res = fc.getFacetResults().get(0);
|
||||||
|
assertEquals(10, res.getNumValidDescendants());
|
||||||
|
|
||||||
|
IOUtils.close(taxo, taxoDir, r, indexDir);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue