Index: lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java (revision 1460965) +++ lucene/facet/src/java/org/apache/lucene/facet/index/CountingListBuilder.java (working copy) @@ -152,13 +152,16 @@ if (op != OrdinalPolicy.NO_PARENTS) { // need to add parents too int parent = taxoWriter.getParent(ordinal); - while (parent > 0) { - ordinals.ints[ordinals.length++] = parent; - parent = taxoWriter.getParent(parent); + if (parent > 0) { + // only do this if the category is not a dimension itself, otherwise, it was just discarded by the 'if' below + while (parent > 0) { + ordinals.ints[ordinals.length++] = parent; + parent = taxoWriter.getParent(parent); + } + if (op == OrdinalPolicy.ALL_BUT_DIMENSION) { // discard the last added parent, which is the dimension + ordinals.length--; + } } - if (op == OrdinalPolicy.ALL_BUT_DIMENSION) { // discard the last added parent, which is the dimension - ordinals.length--; - } } } return ordinalsEncoder.encode(ordinals); Index: lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (revision 1460965) +++ lucene/facet/src/java/org/apache/lucene/facet/search/FacetsAccumulator.java (working copy) @@ -182,10 +182,12 @@ continue; } CategoryListParams clp = searchParams.indexingParams.getCategoryListParams(fr.categoryPath); - OrdinalPolicy ordinalPolicy = clp .getOrdinalPolicy(fr.categoryPath.components[0]); - if (ordinalPolicy == OrdinalPolicy.NO_PARENTS) { - // rollup values - aggregator.rollupValues(fr, rootOrd, children, siblings, facetArrays); + if (fr.categoryPath.length > 0) { // someone might ask to aggregate the ROOT category + OrdinalPolicy ordinalPolicy = clp.getOrdinalPolicy(fr.categoryPath.components[0]); + if (ordinalPolicy == OrdinalPolicy.NO_PARENTS) { + // rollup values + aggregator.rollupValues(fr, rootOrd, children, siblings, facetArrays); + } } FacetResultsHandler frh = createFacetResultsHandler(fr); Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java (revision 1460965) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestFacetsCollector.java (working copy) @@ -1,6 +1,7 @@ package org.apache.lucene.facet.search; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -190,5 +191,41 @@ IOUtils.close(taxo, taxoDir, r, indexDir); } + + @Test + public void testCountRoot() throws Exception { + // LUCENE-4882: FacetsAccumulator threw NPE if a FacetRequest was defined on CP.EMPTY + 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 = atLeast(30); i > 0; --i) { + Document doc = new Document(); + facetFields.addFields(doc, Arrays.asList(new CategoryPath("a"), new CategoryPath("b"))); + iw.addDocument(doc); + } + + taxonomyWriter.close(); + iw.close(); + + DirectoryReader r = DirectoryReader.open(indexDir); + DirectoryTaxonomyReader taxo = new DirectoryTaxonomyReader(taxoDir); + + FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(CategoryPath.EMPTY, 10)); + + 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); + for (FacetResultNode node : res.getFacetResultNode().subResults) { + assertEquals(r.numDocs(), (int) node.value); + } + + IOUtils.close(taxo, taxoDir, r, indexDir); + } }