/**
   * Note: if you use a counting {@link Facets} implementation, you can amortize the sampled counts
   * by calling this method. Uses the {@link FacetsConfig} and the {@link IndexSearcher} to
   * determine the upper bound for each facet value.
   */
  public FacetResult amortizeFacetCounts(
      FacetResult res, FacetsConfig config, IndexSearcher searcher) throws IOException {
    if (res == null || totalHits <= sampleSize) {
      return res;
    }

    LabelAndValue[] fixedLabelValues = new LabelAndValue[res.labelValues.length];
    IndexReader reader = searcher.getIndexReader();
    DimConfig dimConfig = config.getDimConfig(res.dim);

    // +2 to prepend dimension, append child label
    String[] childPath = new String[res.path.length + 2];
    childPath[0] = res.dim;

    System.arraycopy(res.path, 0, childPath, 1, res.path.length); // reuse

    for (int i = 0; i < res.labelValues.length; i++) {
      childPath[res.path.length + 1] = res.labelValues[i].label;
      String fullPath = FacetsConfig.pathToString(childPath, childPath.length);
      int max = reader.docFreq(new Term(dimConfig.indexFieldName, fullPath));
      int correctedCount = (int) (res.labelValues[i].value.doubleValue() / samplingRate);
      correctedCount = Math.min(max, correctedCount);
      fixedLabelValues[i] = new LabelAndValue(res.labelValues[i].label, correctedCount);
    }

    // cap the total count on the total number of non-deleted documents in the reader
    int correctedTotalCount = res.value.intValue();
    if (correctedTotalCount > 0) {
      correctedTotalCount =
          Math.min(reader.numDocs(), (int) (res.value.doubleValue() / samplingRate));
    }

    return new FacetResult(
        res.dim, res.path, correctedTotalCount, fixedLabelValues, res.childCount);
  }
  public void testTermNonDefault() {
    String aField = config.getDimConfig("a").indexFieldName;
    Term termA = DrillDownQuery.term(aField, "a");
    assertEquals(new Term(aField, "a"), termA);

    String bField = config.getDimConfig("b").indexFieldName;
    Term termB = DrillDownQuery.term(bField, "b");
    assertEquals(new Term(bField, "b"), termB);
  }
  @BeforeClass
  public static void beforeClassDrillDownQueryTest() throws Exception {
    dir = newDirectory();
    Random r = random();
    RandomIndexWriter writer =
        new RandomIndexWriter(
            r,
            dir,
            newIndexWriterConfig(
                TEST_VERSION_CURRENT, new MockAnalyzer(r, MockTokenizer.KEYWORD, false)));

    taxoDir = newDirectory();
    TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
    config = new FacetsConfig();

    // Randomize the per-dim config:
    config.setHierarchical("a", random().nextBoolean());
    config.setMultiValued("a", random().nextBoolean());
    if (random().nextBoolean()) {
      config.setIndexFieldName("a", "$a");
    }
    config.setRequireDimCount("a", true);

    config.setHierarchical("b", random().nextBoolean());
    config.setMultiValued("b", random().nextBoolean());
    if (random().nextBoolean()) {
      config.setIndexFieldName("b", "$b");
    }
    config.setRequireDimCount("b", true);

    for (int i = 0; i < 100; i++) {
      Document doc = new Document();
      if (i % 2 == 0) { // 50
        doc.add(new TextField("content", "foo", Field.Store.NO));
      }
      if (i % 3 == 0) { // 33
        doc.add(new TextField("content", "bar", Field.Store.NO));
      }
      if (i % 4 == 0) { // 25
        if (r.nextBoolean()) {
          doc.add(new FacetField("a", "1"));
        } else {
          doc.add(new FacetField("a", "2"));
        }
      }
      if (i % 5 == 0) { // 20
        doc.add(new FacetField("b", "1"));
      }
      writer.addDocument(config.build(taxoWriter, doc));
    }

    taxoWriter.close();
    reader = writer.getReader();
    writer.close();

    taxo = new DirectoryTaxonomyReader(taxoDir);
  }