mirror of https://github.com/apache/lucene.git
LUCENE-9385: Add FacetsConfig option to control which drill-down terms are indexed for a FacetLabel (#25)
This commit is contained in:
parent
3596e05e5c
commit
3648a1020a
|
@ -65,6 +65,44 @@ public class FacetsConfig {
|
||||||
// int/float/bytes in a single indexed field:
|
// int/float/bytes in a single indexed field:
|
||||||
private final Map<String, String> assocDimTypes = new ConcurrentHashMap<>();
|
private final Map<String, String> 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
|
* Holds the configuration for one dimension
|
||||||
*
|
*
|
||||||
|
@ -83,11 +121,8 @@ public class FacetsConfig {
|
||||||
*/
|
*/
|
||||||
public boolean requireDimCount;
|
public boolean requireDimCount;
|
||||||
|
|
||||||
/**
|
/** Default drill down terms indexing option that index all. */
|
||||||
* True if drilling down by a whole dimension, to match all documents that had any value for
|
public DrillDownTermsIndexing drillDownTermsIndexing = DrillDownTermsIndexing.ALL;
|
||||||
* this dimension, is necessary (default is true)
|
|
||||||
*/
|
|
||||||
public boolean requireDimensionDrillDown = true;
|
|
||||||
|
|
||||||
/** Actual field where this dimension's facet labels should be indexed */
|
/** Actual field where this dimension's facet labels should be indexed */
|
||||||
public String indexFieldName = DEFAULT_INDEX_FIELD_NAME;
|
public String indexFieldName = DEFAULT_INDEX_FIELD_NAME;
|
||||||
|
@ -115,44 +150,44 @@ public class FacetsConfig {
|
||||||
|
|
||||||
/** Get the current configuration for a dimension. */
|
/** Get the current configuration for a dimension. */
|
||||||
public DimConfig getDimConfig(String dimName) {
|
public DimConfig getDimConfig(String dimName) {
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
DimConfig dimConfig = fieldTypes.get(dimName);
|
||||||
if (ft == null) {
|
if (dimConfig == null) {
|
||||||
ft = getDefaultDimConfig();
|
dimConfig = getDefaultDimConfig();
|
||||||
}
|
}
|
||||||
return ft;
|
return dimConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pass {@code true} if this dimension is hierarchical (has depth > 1 paths). */
|
/** Pass {@code true} if this dimension is hierarchical (has depth > 1 paths). */
|
||||||
public synchronized void setHierarchical(String dimName, boolean v) {
|
public synchronized void setHierarchical(String dimName, boolean v) {
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
DimConfig dimConfig = fieldTypes.get(dimName);
|
||||||
if (ft == null) {
|
if (dimConfig == null) {
|
||||||
ft = new DimConfig();
|
dimConfig = new DimConfig();
|
||||||
fieldTypes.put(dimName, ft);
|
fieldTypes.put(dimName, dimConfig);
|
||||||
}
|
}
|
||||||
ft.hierarchical = v;
|
dimConfig.hierarchical = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pass {@code true} if this dimension may have more than one value per document. */
|
/** Pass {@code true} if this dimension may have more than one value per document. */
|
||||||
public synchronized void setMultiValued(String dimName, boolean v) {
|
public synchronized void setMultiValued(String dimName, boolean value) {
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
DimConfig dimConfig = fieldTypes.get(dimName);
|
||||||
if (ft == null) {
|
if (dimConfig == null) {
|
||||||
ft = new DimConfig();
|
dimConfig = new DimConfig();
|
||||||
fieldTypes.put(dimName, ft);
|
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
|
* Pass {@code true} if at search time you require accurate counts of the dimension, i.e. how many
|
||||||
* hits have this dimension.
|
* hits have this dimension.
|
||||||
*/
|
*/
|
||||||
public synchronized void setRequireDimCount(String dimName, boolean v) {
|
public synchronized void setRequireDimCount(String dimName, boolean value) {
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
DimConfig dimConfig = fieldTypes.get(dimName);
|
||||||
if (ft == null) {
|
if (dimConfig == null) {
|
||||||
ft = new DimConfig();
|
dimConfig = new DimConfig();
|
||||||
fieldTypes.put(dimName, ft);
|
fieldTypes.put(dimName, dimConfig);
|
||||||
}
|
}
|
||||||
ft.requireDimCount = v;
|
dimConfig.requireDimCount = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,22 +195,42 @@ public class FacetsConfig {
|
||||||
* by the taxonomy based facet methods.
|
* by the taxonomy based facet methods.
|
||||||
*/
|
*/
|
||||||
public synchronized void setIndexFieldName(String dimName, String indexFieldName) {
|
public synchronized void setIndexFieldName(String dimName, String indexFieldName) {
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
DimConfig dimConfig = fieldTypes.get(dimName);
|
||||||
if (ft == null) {
|
if (dimConfig == null) {
|
||||||
ft = new DimConfig();
|
dimConfig = new DimConfig();
|
||||||
fieldTypes.put(dimName, ft);
|
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) {
|
* Specify whether drill down on the dimension is necessary.
|
||||||
DimConfig ft = fieldTypes.get(dimName);
|
*
|
||||||
if (ft == null) {
|
* @deprecated Use {@link FacetsConfig#setDrillDownTermsIndexing(String, DrillDownTermsIndexing)}
|
||||||
ft = new DimConfig();
|
* instead
|
||||||
fieldTypes.put(dimName, ft);
|
*/
|
||||||
|
@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}. */
|
/** Returns map of field name to {@link DimConfig}. */
|
||||||
|
@ -308,8 +363,6 @@ public class FacetsConfig {
|
||||||
processSSDVFacetFields(dvByField, result);
|
processSSDVFacetFields(dvByField, result);
|
||||||
processAssocFacetFields(taxoWriter, assocByField, result);
|
processAssocFacetFields(taxoWriter, assocByField, result);
|
||||||
|
|
||||||
// System.out.println("add stored: " + addedStoredFields);
|
|
||||||
|
|
||||||
for (IndexableField field : doc.getFields()) {
|
for (IndexableField field : doc.getFields()) {
|
||||||
IndexableFieldType ft = field.fieldType();
|
IndexableFieldType ft = field.fieldType();
|
||||||
if (ft != FacetField.TYPE
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,15 +380,13 @@ public class FacetsConfig {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
for (Map.Entry<String, List<FacetField>> ent : byField.entrySet()) {
|
for (Map.Entry<String, List<FacetField>> ent : byField.entrySet()) {
|
||||||
|
|
||||||
String indexFieldName = ent.getKey();
|
String indexFieldName = ent.getKey();
|
||||||
// System.out.println(" indexFieldName=" + indexFieldName + " fields=" + ent.getValue());
|
|
||||||
|
|
||||||
IntsRefBuilder ordinals = new IntsRefBuilder();
|
IntsRefBuilder ordinals = new IntsRefBuilder();
|
||||||
for (FacetField facetField : ent.getValue()) {
|
for (FacetField facetField : ent.getValue()) {
|
||||||
|
|
||||||
FacetsConfig.DimConfig ft = getDimConfig(facetField.dim);
|
FacetsConfig.DimConfig dimConfig = getDimConfig(facetField.dim);
|
||||||
if (facetField.path.length > 1 && ft.hierarchical == false) {
|
if (facetField.path.length > 1 && dimConfig.hierarchical == false) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"dimension \""
|
"dimension \""
|
||||||
+ facetField.dim
|
+ facetField.dim
|
||||||
|
@ -347,16 +395,13 @@ public class FacetsConfig {
|
||||||
+ " components");
|
+ " components");
|
||||||
}
|
}
|
||||||
|
|
||||||
FacetLabel cp = new FacetLabel(facetField.dim, facetField.path);
|
FacetLabel facetLabel = new FacetLabel(facetField.dim, facetField.path);
|
||||||
|
|
||||||
checkTaxoWriter(taxoWriter);
|
checkTaxoWriter(taxoWriter);
|
||||||
int ordinal = taxoWriter.addCategory(cp);
|
int ordinal = taxoWriter.addCategory(facetLabel);
|
||||||
ordinals.append(ordinal);
|
ordinals.append(ordinal);
|
||||||
// System.out.println("ords[" + (ordinals.length-1) + "]=" + ordinal);
|
|
||||||
// System.out.println(" add cp=" + cp);
|
|
||||||
|
|
||||||
if (ft.multiValued && (ft.hierarchical || ft.requireDimCount)) {
|
if (dimConfig.multiValued && (dimConfig.hierarchical || dimConfig.requireDimCount)) {
|
||||||
// System.out.println(" add parents");
|
|
||||||
// Add all parents too:
|
// Add all parents too:
|
||||||
int parent = taxoWriter.getParent(ordinal);
|
int parent = taxoWriter.getParent(ordinal);
|
||||||
while (parent > 0) {
|
while (parent > 0) {
|
||||||
|
@ -364,22 +409,13 @@ public class FacetsConfig {
|
||||||
parent = taxoWriter.getParent(parent);
|
parent = taxoWriter.getParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ft.requireDimCount == false) {
|
if (dimConfig.requireDimCount == false) {
|
||||||
// Remove last (dimension) ord:
|
// Remove last (dimension) ord:
|
||||||
ordinals.setLength(ordinals.length() - 1);
|
ordinals.setLength(ordinals.length() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drill down:
|
indexDrillDownTerms(doc, indexFieldName, dimConfig, facetLabel);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Facet counts:
|
// 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(
|
private void processSSDVFacetFields(
|
||||||
Map<String, List<SortedSetDocValuesFacetField>> byField, Document doc) throws IOException {
|
Map<String, List<SortedSetDocValuesFacetField>> byField, Document doc) {
|
||||||
// System.out.println("process SSDV: " + byField);
|
|
||||||
for (Map.Entry<String, List<SortedSetDocValuesFacetField>> ent : byField.entrySet()) {
|
for (Map.Entry<String, List<SortedSetDocValuesFacetField>> ent : byField.entrySet()) {
|
||||||
|
|
||||||
String indexFieldName = ent.getKey();
|
String indexFieldName = ent.getKey();
|
||||||
// System.out.println(" field=" + indexFieldName);
|
|
||||||
|
|
||||||
for (SortedSetDocValuesFacetField facetField : ent.getValue()) {
|
for (SortedSetDocValuesFacetField facetField : ent.getValue()) {
|
||||||
FacetLabel cp = new FacetLabel(facetField.dim, facetField.label);
|
FacetLabel facetLabel = new FacetLabel(facetField.dim, facetField.label);
|
||||||
String fullPath = pathToString(cp.components, cp.length);
|
String fullPath = pathToString(facetLabel.components, facetLabel.length);
|
||||||
// System.out.println("add " + fullPath);
|
|
||||||
|
|
||||||
// For facet counts:
|
// For facet counts:
|
||||||
doc.add(new SortedSetDocValuesField(indexFieldName, new BytesRef(fullPath)));
|
doc.add(new SortedSetDocValuesField(indexFieldName, new BytesRef(fullPath)));
|
||||||
|
|
||||||
// For drill-down:
|
// For drill-down:
|
||||||
doc.add(new StringField(indexFieldName, fullPath, Field.Store.NO));
|
indexDrillDownTerms(doc, indexFieldName, getDimConfig(facetField.dim), facetLabel);
|
||||||
|
|
||||||
FacetsConfig.DimConfig ft = getDimConfig(facetField.dim);
|
|
||||||
if (ft.requireDimensionDrillDown) {
|
|
||||||
doc.add(new StringField(indexFieldName, facetField.dim, Field.Store.NO));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,8 +496,8 @@ public class FacetsConfig {
|
||||||
for (AssociationFacetField field : ent.getValue()) {
|
for (AssociationFacetField field : ent.getValue()) {
|
||||||
// NOTE: we don't add parents for associations
|
// NOTE: we don't add parents for associations
|
||||||
checkTaxoWriter(taxoWriter);
|
checkTaxoWriter(taxoWriter);
|
||||||
FacetLabel label = new FacetLabel(field.dim, field.path);
|
FacetLabel facetLabel = new FacetLabel(field.dim, field.path);
|
||||||
int ordinal = taxoWriter.addCategory(label);
|
int ordinal = taxoWriter.addCategory(facetLabel);
|
||||||
if (upto + 4 > bytes.length) {
|
if (upto + 4 > bytes.length) {
|
||||||
bytes = ArrayUtil.grow(bytes, upto + 4);
|
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);
|
System.arraycopy(field.assoc.bytes, field.assoc.offset, bytes, upto, field.assoc.length);
|
||||||
upto += field.assoc.length;
|
upto += field.assoc.length;
|
||||||
|
|
||||||
// Drill down:
|
indexDrillDownTerms(doc, indexFieldName, getDimConfig(field.dim), facetLabel);
|
||||||
for (int i = 1; i <= label.length; i++) {
|
|
||||||
doc.add(
|
|
||||||
new StringField(indexFieldName, pathToString(label.components, i), Field.Store.NO));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
doc.add(new BinaryDocValuesField(indexFieldName, new BytesRef(bytes, 0, upto)));
|
doc.add(new BinaryDocValuesField(indexFieldName, new BytesRef(bytes, 0, upto)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.lucene.analysis.MockTokenizer;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.TextField;
|
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.TaxonomyWriter;
|
||||||
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
|
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
|
||||||
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
|
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
|
||||||
|
@ -299,4 +300,233 @@ public class TestDrillDownQuery extends FacetTestCase {
|
||||||
assertEquals(0, searcher.count(q));
|
assertEquals(0, searcher.count(q));
|
||||||
IOUtils.close(taxoReader, reader, writer, dir, taxoDir);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,95 @@ public class TestSortedSetDocValuesFacets extends FacetTestCase {
|
||||||
IOUtils.close(searcher.getIndexReader(), dir);
|
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
|
// LUCENE-5090
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void testStaleState() throws Exception {
|
public void testStaleState() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue