Terms Facets: Allow to specify a set of terms to exclude in the request, closes #246.

This commit is contained in:
kimchy 2010-07-07 14:41:34 +03:00
parent 2b5458daf6
commit 9578ad3ef1
4 changed files with 90 additions and 7 deletions

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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 {