--- /dev/null
+package org.apache.lucene.facet.search;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+
+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
+ * 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 TestTopKResultsHandlerRandom extends BaseTestTopK {
+
+ private List<FacetResult> countFacets(int partitionSize, int numResults, final boolean doComplement)
+ throws IOException, IllegalAccessException, InstantiationException {
+ Query q = new MatchAllDocsQuery();
+ FacetSearchParams facetSearchParams = searchParamsWithRequests(numResults, partitionSize);
+ FacetsCollector fc = new FacetsCollector(facetSearchParams, indexReader, taxoReader) {
+ @Override
+ protected FacetsAccumulator initFacetsAccumulator(
+ FacetSearchParams facetSearchParams, IndexReader indexReader,
+ TaxonomyReader taxonomyReader) {
+ FacetsAccumulator accumulator = new StandardFacetsAccumulator(facetSearchParams, indexReader, taxonomyReader);
+ double complement = doComplement ? FacetsAccumulator.FORCE_COMPLEMENT : FacetsAccumulator.DISABLE_COMPLEMENT;
+ accumulator.setComplementThreshold(complement);
+ return accumulator;
+ }
+ };
+ searcher.search(q, fc);
+ List<FacetResult> facetResults = fc.getFacetResults();
+ return facetResults;
+ }
+
+ /**
+ * Test that indeed top results are returned, ordered same as all results
+ * also when some facets have the same counts.
+ */
+ @Test
+ public void testTopCountsOrder() throws Exception {
+ for (int partitionSize : partitionSizes) {
+ initIndex(partitionSize);
+
+ /*
+ * Try out faceted search in it's most basic form (no sampling nor complement
+ * that is). In this test lots (and lots..) of randomly generated data is
+ * being indexed, and later on an "over-all" faceted search is performed. The
+ * results are checked against the DF of each facet by itself
+ */
+ List<FacetResult> facetResults = countFacets(partitionSize, 100000, false);
+ assertCountsAndCardinality(facetCountsTruth(), facetResults);
+
+ /*
+ * Try out faceted search with complements. In this test lots (and lots..) of
+ * randomly generated data is being indexed, and later on, a "beta" faceted
+ * search is performed - retrieving ~90% of the documents so complements takes
+ * place in here. The results are checked against the a regular (a.k.a
+ * no-complement, no-sampling) faceted search with the same parameters.
+ */
+ facetResults = countFacets(partitionSize, 100000, true);
+ assertCountsAndCardinality(facetCountsTruth(), facetResults);
+
+ List<FacetResult> allFacetResults = countFacets(partitionSize, 100000, false);
+
+ HashMap<String,Integer> all = new HashMap<String,Integer>();
+ int maxNumNodes = 0;
+ int k = 0;
+ for (FacetResult fr : allFacetResults) {
+ FacetResultNode topResNode = fr.getFacetResultNode();
+ maxNumNodes = Math.max(maxNumNodes, topResNode.getNumSubResults());
+ int prevCount = Integer.MAX_VALUE;
+ int pos = 0;
+ for (FacetResultNode frn: topResNode.getSubResults()) {
+ assertTrue("wrong counts order: prev="+prevCount+" curr="+frn.getValue(), prevCount>=frn.getValue());
+ prevCount = (int) frn.getValue();
+ String key = k+"--"+frn.getLabel()+"=="+frn.getValue();
+ if (VERBOSE) {
+ System.out.println(frn.getLabel() + " - " + frn.getValue() + " "+key+" "+pos);
+ }
+ all.put(key, pos++); // will use this later to verify order of sub-results
+ }
+ k++;
+ }
+
+ // verify that when asking for less results, they are always of highest counts
+ // also verify that the order is stable
+ for (int n=1; n<maxNumNodes; n++) {
+ if (VERBOSE) {
+ System.out.println("------- verify for "+n+" top results");
+ }
+ List<FacetResult> someResults = countFacets(partitionSize, n, false);
+ k = 0;
+ for (FacetResult fr : someResults) {
+ FacetResultNode topResNode = fr.getFacetResultNode();
+ assertTrue("too many results: n="+n+" but got "+topResNode.getNumSubResults(), n>=topResNode.getNumSubResults());
+ int pos = 0;
+ for (FacetResultNode frn: topResNode.getSubResults()) {
+ String key = k+"--"+frn.getLabel()+"=="+frn.getValue();
+ if (VERBOSE) {
+ System.out.println(frn.getLabel() + " - " + frn.getValue() + " "+key+" "+pos);
+ }
+ Integer origPos = all.get(key);
+ assertNotNull("missing in all results: "+frn,origPos);
+ assertEquals("wrong order of sub-results!",pos++, origPos.intValue()); // verify order of sub-results
+ }
+ k++;
+ }
+ }
+
+ closeAll(); // done with this partition
+ }
+ }
+
+}