Terms Facets: Allow to get `all_terms` back (possibly with count 0), closes #647.

This commit is contained in:
kimchy 2011-01-23 16:09:18 +02:00
parent 85ee6eaf10
commit 95b6184135
11 changed files with 185 additions and 24 deletions

View File

@ -38,6 +38,7 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
private String fieldName;
private String[] fieldsNames;
private int size = 10;
private Boolean allTerms;
private String[] exclude;
private String regex;
private int regexFlags = 0;
@ -176,6 +177,15 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
return this;
}
/**
* Sets all possible terms to be loaded, even ones with 0 count. Note, this *should not* be used
* with a field that has many possible terms.
*/
public TermsFacetBuilder allTerms(boolean allTerms) {
this.allTerms = allTerms;
return this;
}
@Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (fieldName == null && fieldsNames == null && script == null) {
throw new SearchSourceBuilderException("field/fields/script must be set on terms facet for facet [" + name + "]");
@ -209,6 +219,9 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
if (comparatorType != null) {
builder.field("order", comparatorType.name().toLowerCase());
}
if (allTerms != null) {
builder.field("all_terms", allTerms);
}
if (script != null) {
builder.field("script", script);

View File

@ -74,6 +74,7 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce
String scriptLang = null;
String script = null;
Map<String, Object> params = null;
boolean allTerms = false;
String currentFieldName = null;
XContentParser.Token token;
@ -105,6 +106,8 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce
script = parser.text();
} else if ("size".equals(currentFieldName)) {
size = parser.intValue();
} else if ("all_terms".equals(currentFieldName) || "allTerms".equals(currentFieldName)) {
allTerms = parser.booleanValue();
} else if ("regex".equals(currentFieldName)) {
regex = parser.text();
} else if ("regex_flags".equals(currentFieldName) || "regexFlags".equals(currentFieldName)) {
@ -128,7 +131,7 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce
pattern = Regex.compile(regex, regexFlags);
}
if (fieldsNames != null) {
return new FieldsTermsStringFacetCollector(facetName, fieldsNames, size, comparatorType, context, excluded, pattern, scriptLang, script, params);
return new FieldsTermsStringFacetCollector(facetName, fieldsNames, size, comparatorType, allTerms, context, excluded, pattern, scriptLang, script, params);
}
if (field == null && fieldsNames == null && script != null) {
return new ScriptTermsStringFieldFacetCollector(facetName, size, comparatorType, context, excluded, pattern, scriptLang, script, params);
@ -137,20 +140,20 @@ public class TermsFacetProcessor extends AbstractComponent implements FacetProce
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(field);
if (fieldMapper != null) {
if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.LONG) {
return new TermsLongFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsLongFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
} else if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.DOUBLE) {
return new TermsDoubleFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsDoubleFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
} else if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.INT) {
return new TermsIntFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsIntFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
} else if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.FLOAT) {
return new TermsFloatFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsFloatFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
} else if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.SHORT) {
return new TermsShortFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsShortFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
} else if (fieldMapper.fieldDataType() == FieldDataType.DefaultTypes.BYTE) {
return new TermsByteFacetCollector(facetName, field, size, comparatorType, context, scriptLang, script, params);
return new TermsByteFacetCollector(facetName, field, size, comparatorType, allTerms, context, scriptLang, script, params);
}
}
return new TermsStringFacetCollector(facetName, field, size, comparatorType, context, excluded, pattern, scriptLang, script, params);
return new TermsStringFacetCollector(facetName, field, size, comparatorType, allTerms, context, excluded, pattern, scriptLang, script, params);
}
@Override public Facet reduce(String name, List<Facet> facets) {

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -73,7 +74,7 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsByteFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsByteFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
ByteFieldData fieldData = (ByteFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -194,7 +206,7 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements ByteFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements ByteFieldData.ValueInDocProc, ByteFieldData.ValueProc {
private final TByteIntHashMap facets;
@ -204,6 +216,10 @@ public class TermsByteFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(byte value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, byte value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -73,7 +74,7 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsDoubleFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsDoubleFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
DoubleFieldData fieldData = (DoubleFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -194,7 +206,7 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements DoubleFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements DoubleFieldData.ValueInDocProc, DoubleFieldData.ValueProc {
private final TDoubleIntHashMap facets;
@ -204,6 +216,10 @@ public class TermsDoubleFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(double value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, double value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -73,7 +74,7 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsFloatFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsFloatFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
FloatFieldData fieldData = (FloatFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -194,7 +206,7 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements FloatFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements FloatFieldData.ValueInDocProc, FloatFieldData.ValueProc {
private final TFloatIntHashMap facets;
@ -204,6 +216,10 @@ public class TermsFloatFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(float value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, float value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -73,7 +74,7 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsIntFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsIntFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
IntFieldData fieldData = (IntFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -194,7 +206,7 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements IntFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements IntFieldData.ValueInDocProc, IntFieldData.ValueProc {
private final TIntIntHashMap facets;
@ -204,6 +216,10 @@ public class TermsIntFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(int value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, int value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -74,7 +75,7 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsLongFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsLongFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -112,6 +113,17 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
LongFieldData fieldData = (LongFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -195,7 +207,7 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements LongFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements LongFieldData.ValueInDocProc, LongFieldData.ValueProc {
private final TLongIntHashMap facets;
@ -205,6 +217,10 @@ public class TermsLongFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(long value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, long value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -73,7 +74,7 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsShortFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsShortFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
ShortFieldData fieldData = (ShortFieldData) fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -194,7 +206,7 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements ShortFieldData.ValueInDocProc {
public static class StaticAggregatorValueProc implements ShortFieldData.ValueInDocProc, ShortFieldData.ValueProc {
private final TShortIntHashMap facets;
@ -204,6 +216,10 @@ public class TermsShortFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(short value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, short value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -33,6 +33,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
@ -67,7 +68,7 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public FieldsTermsStringFacetCollector(String facetName, String[] fieldsNames, int size, InternalStringTermsFacet.ComparatorType comparatorType, SearchContext context,
public FieldsTermsStringFacetCollector(String facetName, String[] fieldsNames, int size, InternalStringTermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
ImmutableSet<String> excluded, Pattern pattern, String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -104,6 +105,19 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(TermsStringFacetCollector.popFacets(), excluded, pattern, this.script);
}
if (allTerms) {
try {
for (int i = 0; i < fieldsNames.length; i++) {
for (IndexReader reader : context.searcher().subReaders()) {
FieldData fieldData = fieldDataCache.cache(fieldsDataType[i], reader, indexFieldsNames[i]);
fieldData.forEachValue(aggregator);
}
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -185,7 +199,7 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements FieldData.StringValueInDocProc {
public static class StaticAggregatorValueProc implements FieldData.StringValueInDocProc, FieldData.StringValueProc {
private final TObjectIntHashMap<String> facets;
@ -195,6 +209,10 @@ public class FieldsTermsStringFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(String value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, String value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.search.SearchScript;
import org.elasticsearch.search.facet.AbstractFacetCollector;
import org.elasticsearch.search.facet.Facet;
import org.elasticsearch.search.facet.FacetPhaseExecutionException;
import org.elasticsearch.search.facet.terms.TermsFacet;
import org.elasticsearch.search.internal.SearchContext;
@ -76,7 +77,7 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
private final SearchScript script;
public TermsStringFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, SearchContext context,
public TermsStringFacetCollector(String facetName, String fieldName, int size, TermsFacet.ComparatorType comparatorType, boolean allTerms, SearchContext context,
ImmutableSet<String> excluded, Pattern pattern, String scriptLang, String script, Map<String, Object> params) {
super(facetName);
this.fieldDataCache = context.fieldDataCache();
@ -111,6 +112,17 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
} else {
aggregator = new AggregatorValueProc(popFacets(), excluded, pattern, this.script);
}
if (allTerms) {
try {
for (IndexReader reader : context.searcher().subReaders()) {
FieldData fieldData = fieldDataCache.cache(fieldDataType, reader, indexFieldName);
fieldData.forEachValue(aggregator);
}
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "failed to load all terms", e);
}
}
}
@Override protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
@ -206,7 +218,7 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
}
}
public static class StaticAggregatorValueProc implements FieldData.StringValueInDocProc {
public static class StaticAggregatorValueProc implements FieldData.StringValueInDocProc, FieldData.StringValueProc {
private final TObjectIntHashMap<String> facets;
@ -216,6 +228,10 @@ public class TermsStringFacetCollector extends AbstractFacetCollector {
this.facets = facets;
}
@Override public void onValue(String value) {
facets.putIfAbsent(value, 0);
}
@Override public void onValue(int docId, String value) {
facets.adjustOrPutValue(value, 1, 1);
}

View File

@ -552,6 +552,21 @@ public class SimpleFacetsTests extends AbstractNodesTests {
assertThat(facet.entries().get(3).term(), anyOf(equalTo("zzz"), equalTo("xxx")));
assertThat(facet.entries().get(3).count(), equalTo(1));
searchResponse = client.prepareSearch()
.setQuery(termQuery("xxx", "yyy")) // don't match anything
.addFacet(termsFacet("facet1").field("tag").size(10).allTerms(true))
.execute().actionGet();
facet = searchResponse.facets().facet("facet1");
assertThat(facet.name(), equalTo("facet1"));
assertThat(facet.entries().size(), equalTo(3));
assertThat(facet.entries().get(0).term(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz")));
assertThat(facet.entries().get(0).count(), equalTo(0));
assertThat(facet.entries().get(1).term(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz")));
assertThat(facet.entries().get(1).count(), equalTo(0));
assertThat(facet.entries().get(2).term(), anyOf(equalTo("xxx"), equalTo("yyy"), equalTo("zzz")));
assertThat(facet.entries().get(2).count(), equalTo(0));
// Script Field
searchResponse = client.prepareSearch()