Terms Facets: Allow to specify a set of terms to exclude in the request, closes #246.
This commit is contained in:
parent
2b5458daf6
commit
9578ad3ef1
|
@ -32,6 +32,7 @@ import java.io.IOException;
|
|||
public class TermsFacetBuilder extends AbstractFacetBuilder {
|
||||
private String fieldName;
|
||||
private int size = 10;
|
||||
private String[] exclude;
|
||||
|
||||
public TermsFacetBuilder(String name) {
|
||||
super(name);
|
||||
|
@ -52,6 +53,11 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TermsFacetBuilder exclude(String... exclude) {
|
||||
this.exclude = exclude;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TermsFacetBuilder size(int size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
|
@ -66,6 +72,13 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
|
|||
builder.startObject(TermsFacetCollectorParser.NAME);
|
||||
builder.field("field", fieldName);
|
||||
builder.field("size", size);
|
||||
if (exclude != null) {
|
||||
builder.startArray("exclude");
|
||||
for (String ex : exclude) {
|
||||
builder.value(ex);
|
||||
}
|
||||
builder.endArray();
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
if (filter != null) {
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.elasticsearch.search.facets.terms;
|
|||
import org.apache.lucene.index.IndexReader;
|
||||
import org.elasticsearch.common.collect.BoundedTreeSet;
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.common.thread.ThreadLocals;
|
||||
import org.elasticsearch.common.trove.TObjectIntHashMap;
|
||||
import org.elasticsearch.common.trove.TObjectIntIterator;
|
||||
|
@ -60,12 +61,15 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
|
||||
private FieldData fieldData;
|
||||
|
||||
private final AggregatorValueProc aggregator;
|
||||
private final StaticAggregatorValueProc aggregator;
|
||||
|
||||
public TermsFacetCollector(String facetName, String fieldName, int size, FieldDataCache fieldDataCache, MapperService mapperService) {
|
||||
private final ImmutableSet<String> excluded;
|
||||
|
||||
public TermsFacetCollector(String facetName, String fieldName, int size, FieldDataCache fieldDataCache, MapperService mapperService, ImmutableSet<String> excluded) {
|
||||
super(facetName);
|
||||
this.fieldDataCache = fieldDataCache;
|
||||
this.size = size;
|
||||
this.excluded = excluded;
|
||||
|
||||
FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName);
|
||||
this.fieldName = fieldName;
|
||||
|
@ -76,8 +80,11 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
this.indexFieldName = fieldName;
|
||||
this.fieldDataType = FieldData.Type.STRING;
|
||||
}
|
||||
|
||||
aggregator = new AggregatorValueProc(popFacets());
|
||||
if (excluded.isEmpty()) {
|
||||
aggregator = new StaticAggregatorValueProc(popFacets());
|
||||
} else {
|
||||
aggregator = new AggregatorValueProc(popFacets());
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
|
||||
|
@ -122,11 +129,25 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
}
|
||||
}
|
||||
|
||||
public static class AggregatorValueProc implements FieldData.StringValueInDocProc {
|
||||
public class AggregatorValueProc extends StaticAggregatorValueProc {
|
||||
|
||||
public AggregatorValueProc(TObjectIntHashMap<String> facets) {
|
||||
super(facets);
|
||||
}
|
||||
|
||||
@Override public void onValue(int docId, String value) {
|
||||
if (excluded.contains(value)) {
|
||||
return;
|
||||
}
|
||||
super.onValue(docId, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StaticAggregatorValueProc implements FieldData.StringValueInDocProc {
|
||||
|
||||
private final TObjectIntHashMap<String> facets;
|
||||
|
||||
public AggregatorValueProc(TObjectIntHashMap<String> facets) {
|
||||
public StaticAggregatorValueProc(TObjectIntHashMap<String> facets) {
|
||||
this.facets = facets;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search.facets.terms;
|
||||
|
||||
import org.elasticsearch.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.search.facets.collector.FacetCollector;
|
||||
import org.elasticsearch.search.facets.collector.FacetCollectorParser;
|
||||
|
@ -43,9 +44,18 @@ public class TermsFacetCollectorParser implements FacetCollectorParser {
|
|||
|
||||
String fieldName = null;
|
||||
XContentParser.Token token;
|
||||
ImmutableSet<String> excluded = ImmutableSet.of();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
fieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
if ("exclude".equals(fieldName)) {
|
||||
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
builder.add(parser.text());
|
||||
}
|
||||
excluded = builder.build();
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("field".equals(fieldName)) {
|
||||
field = parser.text();
|
||||
|
@ -54,6 +64,6 @@ public class TermsFacetCollectorParser implements FacetCollectorParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
return new TermsFacetCollector(facetName, field, size, context.fieldDataCache(), context.mapperService());
|
||||
return new TermsFacetCollector(facetName, field, size, context.fieldDataCache(), context.mapperService(), excluded);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,6 +165,45 @@ public class SimpleFacetsTests extends AbstractNodesTests {
|
|||
assertThat(facet.entries().size(), equalTo(1));
|
||||
assertThat(facet.entries().get(0).term(), equalTo("111"));
|
||||
assertThat(facet.entries().get(0).count(), equalTo(1));
|
||||
|
||||
searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("facet1").field("tag").size(10))
|
||||
.execute().actionGet();
|
||||
|
||||
facet = searchResponse.facets().facet(TermsFacet.class, "facet1");
|
||||
assertThat(facet.name(), equalTo("facet1"));
|
||||
assertThat(facet.entries().size(), equalTo(3));
|
||||
assertThat(facet.entries().get(0).term(), equalTo("yyy"));
|
||||
assertThat(facet.entries().get(0).count(), equalTo(2));
|
||||
assertThat(facet.entries().get(1).term(), anyOf(equalTo("xxx"), equalTo("zzz")));
|
||||
assertThat(facet.entries().get(1).count(), equalTo(1));
|
||||
assertThat(facet.entries().get(2).term(), anyOf(equalTo("xxx"), equalTo("zzz")));
|
||||
assertThat(facet.entries().get(2).count(), equalTo(1));
|
||||
|
||||
searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("facet1").field("tag").size(1))
|
||||
.execute().actionGet();
|
||||
|
||||
facet = searchResponse.facets().facet(TermsFacet.class, "facet1");
|
||||
assertThat(facet.name(), equalTo("facet1"));
|
||||
assertThat(facet.entries().size(), equalTo(1));
|
||||
assertThat(facet.entries().get(0).term(), equalTo("yyy"));
|
||||
assertThat(facet.entries().get(0).count(), equalTo(2));
|
||||
|
||||
searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("facet1").field("tag").size(10).exclude("yyy"))
|
||||
.execute().actionGet();
|
||||
|
||||
facet = searchResponse.facets().facet(TermsFacet.class, "facet1");
|
||||
assertThat(facet.name(), equalTo("facet1"));
|
||||
assertThat(facet.entries().size(), equalTo(2));
|
||||
assertThat(facet.entries().get(0).term(), anyOf(equalTo("xxx"), equalTo("zzz")));
|
||||
assertThat(facet.entries().get(0).count(), equalTo(1));
|
||||
assertThat(facet.entries().get(1).term(), anyOf(equalTo("xxx"), equalTo("zzz")));
|
||||
assertThat(facet.entries().get(1).count(), equalTo(1));
|
||||
}
|
||||
|
||||
@Test public void testStatsFacets() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue