From 3648a1020a8ab6b729ed53e0360499e624bb0cd1 Mon Sep 17 00:00:00 2001 From: zacharymorn Date: Sat, 27 Mar 2021 09:38:00 -0700 Subject: [PATCH] LUCENE-9385: Add FacetsConfig option to control which drill-down terms are indexed for a FacetLabel (#25) --- .../org/apache/lucene/facet/FacetsConfig.java | 233 +++++++++++------- .../lucene/facet/TestDrillDownQuery.java | 230 +++++++++++++++++ .../TestSortedSetDocValuesFacets.java | 89 +++++++ 3 files changed, 469 insertions(+), 83 deletions(-) diff --git a/lucene/facet/src/java/org/apache/lucene/facet/FacetsConfig.java b/lucene/facet/src/java/org/apache/lucene/facet/FacetsConfig.java index 4d4fedd8c80..fc3d32a4346 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/FacetsConfig.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/FacetsConfig.java @@ -65,6 +65,44 @@ public class FacetsConfig { // int/float/bytes in a single indexed field: private final Map assocDimTypes = new ConcurrentHashMap<>(); + /** + * Drill down terms indexing option to control whether dimension and sub-path terms should be + * indexed. + */ + public enum DrillDownTermsIndexing { + /** + * Index no drill down terms. e.g. for FacetField("a", "foo/bar/baz"), we would index no drill + * down terms at all (not even full-path drill down term). + */ + NONE, + + /** + * Index only full-path drill down terms. No dimension nor sub-path indexing. e.g. for + * FacetField("a", "foo/bar/baz"), we would only index value "a/foo/bar/baz". + */ + FULL_PATH_ONLY, + + /** + * Index sub-path and full-path drill down terms. No dimension indexing. e.g. for + * FacetField("a", "foo/bar/baz"), we would only index values "a/foo", "a/foo/bar", and + * "a/foo/bar/baz". + */ + ALL_PATHS_NO_DIM, + + /** + * Index dimension and full-path drill down terms. No sub-path indexing. e.g. for + * FacetField("a", "foo/bar/baz"), we would only index values "a" and "a/foo/bar/baz". + */ + DIMENSION_AND_FULL_PATH, + + /** + * Index dimension, sub-path and full-path drill down terms. e.g. for FacetField("a", + * "foo/bar/baz"), we would index all values "a", "a/foo", "a/foo/bar", and "a/foo/bar/baz". + * This is the default / existing behavior. + */ + ALL + } + /** * Holds the configuration for one dimension * @@ -83,11 +121,8 @@ public class FacetsConfig { */ public boolean requireDimCount; - /** - * True if drilling down by a whole dimension, to match all documents that had any value for - * this dimension, is necessary (default is true) - */ - public boolean requireDimensionDrillDown = true; + /** Default drill down terms indexing option that index all. */ + public DrillDownTermsIndexing drillDownTermsIndexing = DrillDownTermsIndexing.ALL; /** Actual field where this dimension's facet labels should be indexed */ public String indexFieldName = DEFAULT_INDEX_FIELD_NAME; @@ -115,44 +150,44 @@ public class FacetsConfig { /** Get the current configuration for a dimension. */ public DimConfig getDimConfig(String dimName) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = getDefaultDimConfig(); + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = getDefaultDimConfig(); } - return ft; + return dimConfig; } /** Pass {@code true} if this dimension is hierarchical (has depth > 1 paths). */ public synchronized void setHierarchical(String dimName, boolean v) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = new DimConfig(); - fieldTypes.put(dimName, ft); + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); } - ft.hierarchical = v; + dimConfig.hierarchical = v; } /** Pass {@code true} if this dimension may have more than one value per document. */ - public synchronized void setMultiValued(String dimName, boolean v) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = new DimConfig(); - fieldTypes.put(dimName, ft); + public synchronized void setMultiValued(String dimName, boolean value) { + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); } - ft.multiValued = v; + dimConfig.multiValued = value; } /** * Pass {@code true} if at search time you require accurate counts of the dimension, i.e. how many * hits have this dimension. */ - public synchronized void setRequireDimCount(String dimName, boolean v) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = new DimConfig(); - fieldTypes.put(dimName, ft); + public synchronized void setRequireDimCount(String dimName, boolean value) { + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); } - ft.requireDimCount = v; + dimConfig.requireDimCount = value; } /** @@ -160,22 +195,42 @@ public class FacetsConfig { * by the taxonomy based facet methods. */ public synchronized void setIndexFieldName(String dimName, String indexFieldName) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = new DimConfig(); - fieldTypes.put(dimName, ft); + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); } - ft.indexFieldName = indexFieldName; + dimConfig.indexFieldName = indexFieldName; } - /** Specify whether drill down on just the dimension is necessary. */ - public synchronized void setRequireDimensionDrillDown(String dimName, boolean v) { - DimConfig ft = fieldTypes.get(dimName); - if (ft == null) { - ft = new DimConfig(); - fieldTypes.put(dimName, ft); + /** + * Specify whether drill down on the dimension is necessary. + * + * @deprecated Use {@link FacetsConfig#setDrillDownTermsIndexing(String, DrillDownTermsIndexing)} + * instead + */ + @Deprecated + public synchronized void setRequireDimensionDrillDown(String dimName, boolean value) { + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); } - ft.requireDimensionDrillDown = v; + + dimConfig.drillDownTermsIndexing = + value ? DrillDownTermsIndexing.ALL : DrillDownTermsIndexing.ALL_PATHS_NO_DIM; + } + + /** Specify drill down terms option on the field / dimension. */ + public synchronized void setDrillDownTermsIndexing( + String dimName, DrillDownTermsIndexing drillDownTermsIndexing) { + DimConfig dimConfig = fieldTypes.get(dimName); + if (dimConfig == null) { + dimConfig = new DimConfig(); + fieldTypes.put(dimName, dimConfig); + } + + dimConfig.drillDownTermsIndexing = drillDownTermsIndexing; } /** Returns map of field name to {@link DimConfig}. */ @@ -308,8 +363,6 @@ public class FacetsConfig { processSSDVFacetFields(dvByField, result); processAssocFacetFields(taxoWriter, assocByField, result); - // System.out.println("add stored: " + addedStoredFields); - for (IndexableField field : doc.getFields()) { IndexableFieldType ft = field.fieldType(); if (ft != FacetField.TYPE @@ -319,9 +372,6 @@ public class FacetsConfig { } } - // System.out.println("all indexed: " + allIndexedFields); - // System.out.println("all stored: " + allStoredFields); - return result; } @@ -330,15 +380,13 @@ public class FacetsConfig { throws IOException { for (Map.Entry> ent : byField.entrySet()) { - String indexFieldName = ent.getKey(); - // System.out.println(" indexFieldName=" + indexFieldName + " fields=" + ent.getValue()); IntsRefBuilder ordinals = new IntsRefBuilder(); for (FacetField facetField : ent.getValue()) { - FacetsConfig.DimConfig ft = getDimConfig(facetField.dim); - if (facetField.path.length > 1 && ft.hierarchical == false) { + FacetsConfig.DimConfig dimConfig = getDimConfig(facetField.dim); + if (facetField.path.length > 1 && dimConfig.hierarchical == false) { throw new IllegalArgumentException( "dimension \"" + facetField.dim @@ -347,16 +395,13 @@ public class FacetsConfig { + " components"); } - FacetLabel cp = new FacetLabel(facetField.dim, facetField.path); + FacetLabel facetLabel = new FacetLabel(facetField.dim, facetField.path); checkTaxoWriter(taxoWriter); - int ordinal = taxoWriter.addCategory(cp); + int ordinal = taxoWriter.addCategory(facetLabel); ordinals.append(ordinal); - // System.out.println("ords[" + (ordinals.length-1) + "]=" + ordinal); - // System.out.println(" add cp=" + cp); - if (ft.multiValued && (ft.hierarchical || ft.requireDimCount)) { - // System.out.println(" add parents"); + if (dimConfig.multiValued && (dimConfig.hierarchical || dimConfig.requireDimCount)) { // Add all parents too: int parent = taxoWriter.getParent(ordinal); while (parent > 0) { @@ -364,22 +409,13 @@ public class FacetsConfig { parent = taxoWriter.getParent(parent); } - if (ft.requireDimCount == false) { + if (dimConfig.requireDimCount == false) { // Remove last (dimension) ord: ordinals.setLength(ordinals.length() - 1); } } - // Drill down: - int start; - if (ft.requireDimensionDrillDown) { - start = 1; - } else { - start = 2; - } - for (int i = start; i <= cp.length; i++) { - doc.add(new StringField(indexFieldName, pathToString(cp.components, i), Field.Store.NO)); - } + indexDrillDownTerms(doc, indexFieldName, dimConfig, facetLabel); } // Facet counts: @@ -388,29 +424,64 @@ public class FacetsConfig { } } + private void indexDrillDownTerms( + Document doc, String indexFieldName, DimConfig dimConfig, FacetLabel facetLabel) { + if (dimConfig.drillDownTermsIndexing != DrillDownTermsIndexing.NONE) { + // index full-path drill down term + doc.add( + new StringField( + indexFieldName, + pathToString(facetLabel.components, facetLabel.length), + Field.Store.NO)); + + switch (dimConfig.drillDownTermsIndexing) { + case NONE: + case FULL_PATH_ONLY: + // these two cases are already handled above + break; + case DIMENSION_AND_FULL_PATH: + doc.add( + new StringField( + indexFieldName, pathToString(facetLabel.components, 1), Field.Store.NO)); + break; + case ALL_PATHS_NO_DIM: + for (int i = 2; i < facetLabel.length; i++) { + doc.add( + new StringField( + indexFieldName, pathToString(facetLabel.components, i), Field.Store.NO)); + } + break; + case ALL: + for (int i = 1; i < facetLabel.length; i++) { + doc.add( + new StringField( + indexFieldName, pathToString(facetLabel.components, i), Field.Store.NO)); + } + break; + default: + throw new AssertionError( + "Drill down term indexing option " + + dimConfig.drillDownTermsIndexing + + " is not supported."); + } + } + } + private void processSSDVFacetFields( - Map> byField, Document doc) throws IOException { - // System.out.println("process SSDV: " + byField); + Map> byField, Document doc) { for (Map.Entry> ent : byField.entrySet()) { String indexFieldName = ent.getKey(); - // System.out.println(" field=" + indexFieldName); for (SortedSetDocValuesFacetField facetField : ent.getValue()) { - FacetLabel cp = new FacetLabel(facetField.dim, facetField.label); - String fullPath = pathToString(cp.components, cp.length); - // System.out.println("add " + fullPath); + FacetLabel facetLabel = new FacetLabel(facetField.dim, facetField.label); + String fullPath = pathToString(facetLabel.components, facetLabel.length); // For facet counts: doc.add(new SortedSetDocValuesField(indexFieldName, new BytesRef(fullPath))); // For drill-down: - doc.add(new StringField(indexFieldName, fullPath, Field.Store.NO)); - - FacetsConfig.DimConfig ft = getDimConfig(facetField.dim); - if (ft.requireDimensionDrillDown) { - doc.add(new StringField(indexFieldName, facetField.dim, Field.Store.NO)); - } + indexDrillDownTerms(doc, indexFieldName, getDimConfig(facetField.dim), facetLabel); } } } @@ -425,8 +496,8 @@ public class FacetsConfig { for (AssociationFacetField field : ent.getValue()) { // NOTE: we don't add parents for associations checkTaxoWriter(taxoWriter); - FacetLabel label = new FacetLabel(field.dim, field.path); - int ordinal = taxoWriter.addCategory(label); + FacetLabel facetLabel = new FacetLabel(field.dim, field.path); + int ordinal = taxoWriter.addCategory(facetLabel); if (upto + 4 > bytes.length) { bytes = ArrayUtil.grow(bytes, upto + 4); } @@ -441,11 +512,7 @@ public class FacetsConfig { System.arraycopy(field.assoc.bytes, field.assoc.offset, bytes, upto, field.assoc.length); upto += field.assoc.length; - // Drill down: - for (int i = 1; i <= label.length; i++) { - doc.add( - new StringField(indexFieldName, pathToString(label.components, i), Field.Store.NO)); - } + indexDrillDownTerms(doc, indexFieldName, getDimConfig(field.dim), facetLabel); } doc.add(new BinaryDocValuesField(indexFieldName, new BytesRef(bytes, 0, upto))); } diff --git a/lucene/facet/src/test/org/apache/lucene/facet/TestDrillDownQuery.java b/lucene/facet/src/test/org/apache/lucene/facet/TestDrillDownQuery.java index 722db93a464..e69090fbf80 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/TestDrillDownQuery.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/TestDrillDownQuery.java @@ -23,6 +23,7 @@ import org.apache.lucene.analysis.MockTokenizer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; +import org.apache.lucene.facet.taxonomy.IntAssociationFacetField; import org.apache.lucene.facet.taxonomy.TaxonomyWriter; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader; import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter; @@ -299,4 +300,233 @@ public class TestDrillDownQuery extends FacetTestCase { assertEquals(0, searcher.count(q)); IOUtils.close(taxoReader, reader, writer, dir, taxoDir); } + + public void testSkipDrillDownTermsIndexing() throws Exception { + Directory dir = newDirectory(); + RandomIndexWriter writer = + new RandomIndexWriter( + random(), + dir, + newIndexWriterConfig(new MockAnalyzer(random(), MockTokenizer.KEYWORD, false))); + Directory taxoDir = newDirectory(); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); + FacetsConfig config = new FacetsConfig(); + config.setDrillDownTermsIndexing("a", FacetsConfig.DrillDownTermsIndexing.FULL_PATH_ONLY); + config.setDrillDownTermsIndexing("b", FacetsConfig.DrillDownTermsIndexing.FULL_PATH_ONLY); + + Document doc = new Document(); + doc.add(new FacetField("a", "1")); + doc.add(new FacetField("b", "2")); + writer.addDocument(config.build(taxoWriter, doc)); + taxoWriter.close(); + + IndexReader reader = writer.getReader(); + DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); + IndexSearcher searcher = newSearcher(reader); + + DrillDownQuery q = new DrillDownQuery(config); + q.add("a"); + // no hits because we disabled dimension drill down completely + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "1"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b"); + // no hits because we disabled dimension drill down completely + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b", "2"); + assertEquals(1, searcher.count(q)); + + IOUtils.close(taxoReader, reader, writer, dir, taxoDir); + } + + public void testDrillDownTermsDifferentOptions() throws Exception { + Directory dir = newDirectory(); + RandomIndexWriter writer = + new RandomIndexWriter( + random(), + dir, + newIndexWriterConfig(new MockAnalyzer(random(), MockTokenizer.KEYWORD, false))); + Directory taxoDir = newDirectory(); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); + FacetsConfig config = new FacetsConfig(); + config.setHierarchical("a", true); + config.setHierarchical("b", true); + config.setHierarchical("c", true); + config.setHierarchical("d", true); + config.setHierarchical("e", true); + config.setDrillDownTermsIndexing("a", FacetsConfig.DrillDownTermsIndexing.NONE); + config.setDrillDownTermsIndexing("b", FacetsConfig.DrillDownTermsIndexing.FULL_PATH_ONLY); + config.setDrillDownTermsIndexing("c", FacetsConfig.DrillDownTermsIndexing.ALL_PATHS_NO_DIM); + config.setDrillDownTermsIndexing( + "d", FacetsConfig.DrillDownTermsIndexing.DIMENSION_AND_FULL_PATH); + config.setDrillDownTermsIndexing("e", FacetsConfig.DrillDownTermsIndexing.ALL); + config.setDrillDownTermsIndexing("f", FacetsConfig.DrillDownTermsIndexing.NONE); + config.setIndexFieldName("f", "facet-for-f"); + + Document doc = new Document(); + doc.add(new FacetField("a", "a1", "a2", "a3")); + doc.add(new FacetField("b", "b1", "b2", "b3")); + doc.add(new FacetField("c", "c1", "c2", "c3")); + doc.add(new FacetField("d", "d1", "d2", "d3")); + doc.add(new FacetField("e", "e1", "e2", "e3")); + doc.add(new IntAssociationFacetField(5, "f", "f1")); + writer.addDocument(config.build(taxoWriter, doc)); + taxoWriter.close(); + + IndexReader reader = writer.getReader(); + DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); + IndexSearcher searcher = newSearcher(reader); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.NONE option + DrillDownQuery q = new DrillDownQuery(config); + q.add("a"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "a1"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "a1", "a2"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "a1", "a2", "a3"); + assertEquals(0, searcher.count(q)); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.FULL_PATH_ONLY option + q = new DrillDownQuery(config); + q.add("b"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b", "b1"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b", "b1", "b2"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b", "b1", "b2", "b3"); + assertEquals(1, searcher.count(q)); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.ALL_PATHS_NO_DIM option + q = new DrillDownQuery(config); + q.add("c"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("c", "c1"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("c", "c1", "c2"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("c", "c1", "c2", "c3"); + assertEquals(1, searcher.count(q)); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.DIMENSION_AND_FULL_PATH option + q = new DrillDownQuery(config); + q.add("d"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("d", "d1"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("d", "d1", "d2"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("d", "d1", "d2", "d3"); + assertEquals(1, searcher.count(q)); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.ALL option + q = new DrillDownQuery(config); + q.add("e"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("e", "e1"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("e", "e1", "e2"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("e", "e1", "e2", "e3"); + assertEquals(1, searcher.count(q)); + + // Verifies for FacetsConfig.DrillDownTermsIndexing.DIMENSION_AND_FULL_PATH option with + // IntAssociationFacetField + q = new DrillDownQuery(config); + q.add("f"); + assertEquals(0, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("f", "f1"); + assertEquals(0, searcher.count(q)); + + IOUtils.close(taxoReader, reader, writer, dir, taxoDir); + } + + public void testDrillDownTermsDefaultWithHierarchicalSetting() throws Exception { + Directory dir = newDirectory(); + RandomIndexWriter writer = + new RandomIndexWriter( + random(), + dir, + newIndexWriterConfig(new MockAnalyzer(random(), MockTokenizer.KEYWORD, false))); + Directory taxoDir = newDirectory(); + TaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir); + FacetsConfig config = new FacetsConfig(); + config.setHierarchical("a", true); + + Document doc = new Document(); + doc.add(new FacetField("a", "1", "2", "3")); + doc.add(new FacetField("b", "4")); + writer.addDocument(config.build(taxoWriter, doc)); + taxoWriter.close(); + + IndexReader reader = writer.getReader(); + DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir); + IndexSearcher searcher = newSearcher(reader); + + DrillDownQuery q = new DrillDownQuery(config); + q.add("a"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "1"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "1", "2"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("a", "1", "2", "3"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b"); + assertEquals(1, searcher.count(q)); + + q = new DrillDownQuery(config); + q.add("b", "4"); + assertEquals(1, searcher.count(q)); + + IOUtils.close(taxoReader, reader, writer, dir, taxoDir); + } } diff --git a/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java b/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java index c20986f6ab3..91a70fcef2f 100644 --- a/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java +++ b/lucene/facet/src/test/org/apache/lucene/facet/sortedset/TestSortedSetDocValuesFacets.java @@ -105,6 +105,95 @@ public class TestSortedSetDocValuesFacets extends FacetTestCase { IOUtils.close(searcher.getIndexReader(), dir); } + public void testDrillDownOptions() throws Exception { + Directory dir = newDirectory(); + + FacetsConfig config = new FacetsConfig(); + config.setDrillDownTermsIndexing("c", FacetsConfig.DrillDownTermsIndexing.NONE); + config.setDrillDownTermsIndexing( + "d", FacetsConfig.DrillDownTermsIndexing.DIMENSION_AND_FULL_PATH); + config.setDrillDownTermsIndexing("e", FacetsConfig.DrillDownTermsIndexing.ALL_PATHS_NO_DIM); + config.setDrillDownTermsIndexing("f", FacetsConfig.DrillDownTermsIndexing.FULL_PATH_ONLY); + config.setDrillDownTermsIndexing("g", FacetsConfig.DrillDownTermsIndexing.ALL); + RandomIndexWriter writer = new RandomIndexWriter(random(), dir); + + Document doc = new Document(); + doc.add(new SortedSetDocValuesFacetField("c", "foo")); + doc.add(new SortedSetDocValuesFacetField("d", "foo")); + doc.add(new SortedSetDocValuesFacetField("e", "foo")); + doc.add(new SortedSetDocValuesFacetField("f", "foo")); + doc.add(new SortedSetDocValuesFacetField("g", "foo")); + writer.addDocument(config.build(doc)); + if (random().nextBoolean()) { + writer.commit(); + } + + doc = new Document(); + doc.add(new SortedSetDocValuesFacetField("a", "foo")); + writer.addDocument(config.build(doc)); + + // NRT open + IndexSearcher searcher = newSearcher(writer.getReader()); + ExecutorService exec = randomExecutorServiceOrNull(); + + // Drill down with different indexing configuration options + DrillDownQuery q = new DrillDownQuery(config); + q.add("c"); + TopDocs hits = searcher.search(q, 1); + assertEquals(0, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("c", "foo"); + hits = searcher.search(q, 1); + assertEquals(0, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("d"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("d", "foo"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("e"); + hits = searcher.search(q, 1); + assertEquals(0, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("e", "foo"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("f"); + hits = searcher.search(q, 1); + assertEquals(0, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("f", "foo"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("g"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + q = new DrillDownQuery(config); + q.add("g", "foo"); + hits = searcher.search(q, 1); + assertEquals(1, hits.totalHits.value); + + if (exec != null) { + exec.shutdownNow(); + } + writer.close(); + IOUtils.close(searcher.getIndexReader(), dir); + } + // LUCENE-5090 @SuppressWarnings("unused") public void testStaleState() throws Exception {