Index: lucene/CHANGES.txt =================================================================== --- lucene/CHANGES.txt (revision 1416935) +++ lucene/CHANGES.txt (working copy) @@ -202,6 +202,13 @@ * LUCENE-4009: Improve TermsFilter.toString (Tim Costermans via Chris Male, Mike McCandless) +Changes in Runtime Behavior + +* LUCENE-4586: Change default ResultMode of FacetRequest to PER_NODE_IN_TREE. + This only affects requests with depth>1. If you execute such requests and + rely on the facet results being returned flat (i.e. no hierarchy), you should + set the ResultMode to GLOBAL_FLAT. (Shai Erera, Gilad Barkai) + Optimizations * LUCENE-2221: oal.util.BitUtil was modified to use Long.bitCount and Index: lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java (revision 1416935) +++ lucene/facet/src/java/org/apache/lucene/facet/search/TopKInEachNodeHandler.java (working copy) @@ -592,7 +592,7 @@ @Override protected boolean leftGoesNow (int ord1, double val1, int ord2, double val2) { - return (val1 < val2); + return (val1 == val2) ? (ord1 < ord2) : (val1 < val2); } } @@ -602,7 +602,7 @@ @Override protected boolean leftGoesNow (int ord1, double val1, int ord2, double val2) { - return (val1 > val2); + return (val1 == val2) ? (ord1 > ord2) : (val1 > val2); } } @@ -656,6 +656,7 @@ this.totalNumOfFacetsConsidered = 0; } + @Override public FacetRequest getFacetRequest() { return this.facetRequest; } Index: lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetRequest.java =================================================================== --- lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetRequest.java (revision 1416935) +++ lucene/facet/src/java/org/apache/lucene/facet/search/params/FacetRequest.java (working copy) @@ -64,7 +64,7 @@ * Default result mode * @see #getResultMode() */ - public static final ResultMode DEFAULT_RESULT_MODE = ResultMode.GLOBAL_FLAT; + public static final ResultMode DEFAULT_RESULT_MODE = ResultMode.PER_NODE_IN_TREE; private final CategoryPath categoryPath; private final int numResults; Index: lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (revision 1416935) +++ lucene/facet/src/test/org/apache/lucene/facet/FacetTestBase.java (working copy) @@ -328,7 +328,7 @@ if (!expectedResults.equals(actualResults)) { System.err.println("Results are not the same!"); System.err.println("Expected:\n" + expectedResults); - System.err.println("Actual" + actualResults); + System.err.println("Actual:\n" + actualResults); throw new NotSameResultError(); } } Index: lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java (revision 1416935) +++ lucene/facet/src/test/org/apache/lucene/facet/search/BaseTestTopK.java (working copy) @@ -61,6 +61,10 @@ return; } currDoc = doc; + // the code below tries to achieve non-uniform distribution of + // categories. Perhaps we can use random.nextGaussian() instead, + // something like nextGaussian() * stdev + maxCategory/2. Or + // try to generate a Zipf distribution. nextInt = random().nextInt(categoriesPow2); nextInt = (int)Math.sqrt(nextInt); } Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (revision 1416935) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestMultipleCategoryLists.java (working copy) @@ -12,6 +12,7 @@ import org.apache.lucene.facet.index.params.PerDimensionIndexingParams; import org.apache.lucene.facet.search.params.CountFacetRequest; import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.params.FacetRequest.ResultMode; import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.search.results.FacetResultNode; import org.apache.lucene.facet.taxonomy.CategoryPath; @@ -122,8 +123,7 @@ // prepare searcher to search against IndexSearcher searcher = newSearcher(ir); - FacetsCollector facetsCollector = performSearch(iParams, tr, ir, - searcher); + FacetsCollector facetsCollector = performSearch(iParams, tr, ir, searcher); // Obtain facets results and hand-test them assertCorrectResults(facetsCollector); @@ -335,16 +335,14 @@ // Faceted search parameters indicate which facets are we interested in FacetSearchParams facetSearchParams = new FacetSearchParams(iParams); - facetSearchParams.addFacetRequest(new CountFacetRequest( - new CategoryPath("Band"), 10)); - CountFacetRequest bandDepth = new CountFacetRequest(new CategoryPath( - "Band"), 10); + facetSearchParams.addFacetRequest(new CountFacetRequest(new CategoryPath("Band"), 10)); + CountFacetRequest bandDepth = new CountFacetRequest(new CategoryPath("Band"), 10); bandDepth.setDepth(2); + // makes it easier to check the results in the test. + bandDepth.setResultMode(ResultMode.GLOBAL_FLAT); facetSearchParams.addFacetRequest(bandDepth); - facetSearchParams.addFacetRequest(new CountFacetRequest( - new CategoryPath("Author"), 10)); - facetSearchParams.addFacetRequest(new CountFacetRequest( - new CategoryPath("Band", "Rock & Pop"), 10)); + facetSearchParams.addFacetRequest(new CountFacetRequest(new CategoryPath("Author"), 10)); + facetSearchParams.addFacetRequest(new CountFacetRequest(new CategoryPath("Band", "Rock & Pop"), 10)); // perform documents search and facets accumulation FacetsCollector facetsCollector = new FacetsCollector(facetSearchParams, ir, tr); Index: lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java =================================================================== --- lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java (revision 1416935) +++ lucene/facet/src/test/org/apache/lucene/facet/search/TestTopKResultsHandler.java (working copy) @@ -9,6 +9,7 @@ import org.apache.lucene.facet.search.params.CountFacetRequest; import org.apache.lucene.facet.search.params.FacetSearchParams; +import org.apache.lucene.facet.search.params.FacetRequest.ResultMode; import org.apache.lucene.facet.search.results.FacetResult; import org.apache.lucene.facet.search.results.FacetResultNode; import org.apache.lucene.facet.taxonomy.CategoryPath; @@ -65,7 +66,7 @@ } /** - * Strait forward test: Adding specific documents with specific facets and + * Straightforward test: Adding specific documents with specific facets and * counting them in the most basic form. */ @Test @@ -79,6 +80,8 @@ sParams.addFacetRequest(new CountFacetRequest(new CategoryPath("a"), 100)); CountFacetRequest cfra = new CountFacetRequest(new CategoryPath("a"), 100); cfra.setDepth(3); + // makes it easier to check the results in the test. + cfra.setResultMode(ResultMode.GLOBAL_FLAT); sParams.addFacetRequest(cfra); sParams.addFacetRequest(new CountFacetRequest(new CategoryPath("a", "b"), 100)); sParams.addFacetRequest(new CountFacetRequest(new CategoryPath("a", "b", "1"), 100)); 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 1416935) +++ lucene/facet/src/test/org/apache/lucene/facet/search/sampling/BaseSampleTestTopK.java (working copy) @@ -14,6 +14,8 @@ 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.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; @@ -43,6 +45,20 @@ /** since there is a chance that this test would fail even if the code is correct, retry the sampling */ protected static final int RETRIES = 10; + @Override + protected FacetSearchParams searchParamsWithRequests(int numResults, int partitionSize) { + FacetSearchParams res = super.searchParamsWithRequests(numResults, partitionSize); + for (FacetRequest req : res.getFacetRequests()) { + // randomize the way we aggregate results + if (random().nextBoolean()) { + req.setResultMode(ResultMode.GLOBAL_FLAT); + } else { + req.setResultMode(ResultMode.PER_NODE_IN_TREE); + } + } + return res; + } + protected abstract FacetsAccumulator getSamplingAccumulator(Sampler sampler, TaxonomyReader taxoReader, IndexReader indexReader, FacetSearchParams searchParams);