add the ability to control the "order" by of terms facet, can either be `term` or `count`. defaults to `count`.
This commit is contained in:
parent
d4547c629f
commit
566ae94478
|
@ -86,6 +86,14 @@ public class InternalTermsFacet implements InternalFacet, TermsFacet {
|
|||
return type();
|
||||
}
|
||||
|
||||
@Override public ComparatorType comparatorType() {
|
||||
return comparatorType;
|
||||
}
|
||||
|
||||
@Override public ComparatorType getComparatorType() {
|
||||
return comparatorType();
|
||||
}
|
||||
|
||||
@Override public List<Entry> entries() {
|
||||
if (!(entries instanceof List)) {
|
||||
entries = ImmutableList.copyOf(entries);
|
||||
|
|
|
@ -26,11 +26,19 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Terms facet allows to return facets of the most popular terms within the search query.
|
||||
*
|
||||
* @author kimchy (shay.banon)
|
||||
*/
|
||||
public interface TermsFacet extends Facet, Iterable<TermsFacet.Entry> {
|
||||
|
||||
/**
|
||||
* Controls how the terms facets are ordered.
|
||||
*/
|
||||
public static enum ComparatorType {
|
||||
/**
|
||||
* Order by the count of each term.
|
||||
*/
|
||||
COUNT((byte) 0, new Comparator<Entry>() {
|
||||
|
||||
@Override public int compare(Entry o1, Entry o2) {
|
||||
|
@ -44,14 +52,17 @@ public interface TermsFacet extends Facet, Iterable<TermsFacet.Entry> {
|
|||
return i;
|
||||
}
|
||||
}),
|
||||
/**
|
||||
* Order by the count of each term.
|
||||
*/
|
||||
TERM((byte) 1, new Comparator<Entry>() {
|
||||
|
||||
@Override public int compare(Entry o1, Entry o2) {
|
||||
int i = o2.term().compareTo(o1.term());
|
||||
int i = o1.term().compareTo(o2.term());
|
||||
if (i == 0) {
|
||||
i = o2.count() - o1.count();
|
||||
i = o1.count() - o2.count();
|
||||
if (i == 0) {
|
||||
i = System.identityHashCode(o2) - System.identityHashCode(o1);
|
||||
i = System.identityHashCode(o1) - System.identityHashCode(o2);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
@ -81,7 +92,16 @@ public interface TermsFacet extends Facet, Iterable<TermsFacet.Entry> {
|
|||
} else if (id == 1) {
|
||||
return TERM;
|
||||
}
|
||||
throw new ElasticSearchIllegalArgumentException("No type argument match for multi count comparator [" + id + "]");
|
||||
throw new ElasticSearchIllegalArgumentException("No type argument match for terms facet comparator [" + id + "]");
|
||||
}
|
||||
|
||||
public static ComparatorType fromString(String type) {
|
||||
if ("count".equals(type)) {
|
||||
return COUNT;
|
||||
} else if ("term".equals(type)) {
|
||||
return TERM;
|
||||
}
|
||||
throw new ElasticSearchIllegalArgumentException("No type argument match for terms facet comparator [" + type + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,11 +132,33 @@ public interface TermsFacet extends Facet, Iterable<TermsFacet.Entry> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The field name the terms were extracted from.
|
||||
*/
|
||||
String fieldName();
|
||||
|
||||
/**
|
||||
* The field name the terms were extracted from.
|
||||
*/
|
||||
String getFieldName();
|
||||
|
||||
/**
|
||||
* The ordering of the results.
|
||||
*/
|
||||
ComparatorType comparatorType();
|
||||
|
||||
/**
|
||||
* The ordering of the results.
|
||||
*/
|
||||
ComparatorType getComparatorType();
|
||||
|
||||
/**
|
||||
* The terms and counts.
|
||||
*/
|
||||
List<Entry> entries();
|
||||
|
||||
/**
|
||||
* The terms and counts.
|
||||
*/
|
||||
List<Entry> getEntries();
|
||||
}
|
|
@ -36,6 +36,7 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
|
|||
private String[] exclude;
|
||||
private String regex;
|
||||
private int regexFlags = 0;
|
||||
private TermsFacet.ComparatorType comparatorType;
|
||||
|
||||
public TermsFacetBuilder(String name) {
|
||||
super(name);
|
||||
|
@ -76,6 +77,11 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TermsFacetBuilder order(TermsFacet.ComparatorType comparatorType) {
|
||||
this.comparatorType = comparatorType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (fieldName == null) {
|
||||
throw new SearchSourceBuilderException("field must be set on terms facet for facet [" + name + "]");
|
||||
|
@ -98,6 +104,9 @@ public class TermsFacetBuilder extends AbstractFacetBuilder {
|
|||
builder.field("regex_flags", Regex.flagsToString(regexFlags));
|
||||
}
|
||||
}
|
||||
if (comparatorType != null) {
|
||||
builder.field("order", comparatorType.name().toLowerCase());
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
addFilterFacetAndGlobal(builder, params);
|
||||
|
|
|
@ -57,6 +57,8 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
|
||||
private final String indexFieldName;
|
||||
|
||||
private final InternalTermsFacet.ComparatorType comparatorType;
|
||||
|
||||
private final int size;
|
||||
|
||||
private final int numberOfShards;
|
||||
|
@ -71,10 +73,11 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
|
||||
private final Pattern pattern;
|
||||
|
||||
public TermsFacetCollector(String facetName, String fieldName, int size, int numberOfShards, FieldDataCache fieldDataCache, MapperService mapperService, ImmutableSet<String> excluded, Pattern pattern) {
|
||||
public TermsFacetCollector(String facetName, String fieldName, int size, InternalTermsFacet.ComparatorType comparatorType, int numberOfShards, FieldDataCache fieldDataCache, MapperService mapperService, ImmutableSet<String> excluded, Pattern pattern) {
|
||||
super(facetName);
|
||||
this.fieldDataCache = fieldDataCache;
|
||||
this.size = size;
|
||||
this.comparatorType = comparatorType;
|
||||
this.numberOfShards = numberOfShards;
|
||||
this.excluded = excluded;
|
||||
this.pattern = pattern;
|
||||
|
@ -107,7 +110,7 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
TObjectIntHashMap<String> facets = aggregator.facets();
|
||||
if (facets.isEmpty()) {
|
||||
pushFacets(facets);
|
||||
return new InternalTermsFacet(facetName, fieldName, InternalTermsFacet.ComparatorType.COUNT, size, ImmutableList.<InternalTermsFacet.Entry>of());
|
||||
return new InternalTermsFacet(facetName, fieldName, comparatorType, size, ImmutableList.<InternalTermsFacet.Entry>of());
|
||||
} else {
|
||||
// we need to fetch facets of "size * numberOfShards" because of problems in how they are distributed across shards
|
||||
BoundedTreeSet<InternalTermsFacet.Entry> ordered = new BoundedTreeSet<InternalTermsFacet.Entry>(InternalTermsFacet.ComparatorType.COUNT.comparator(), size * numberOfShards);
|
||||
|
@ -116,7 +119,7 @@ public class TermsFacetCollector extends AbstractFacetCollector {
|
|||
ordered.add(new InternalTermsFacet.Entry(it.key(), it.value()));
|
||||
}
|
||||
pushFacets(facets);
|
||||
return new InternalTermsFacet(facetName, fieldName, InternalTermsFacet.ComparatorType.COUNT, size, ordered);
|
||||
return new InternalTermsFacet(facetName, fieldName, comparatorType, size, ordered);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public class TermsFacetCollectorParser implements FacetCollectorParser {
|
|||
ImmutableSet<String> excluded = ImmutableSet.of();
|
||||
String regex = null;
|
||||
String regexFlags = null;
|
||||
TermsFacet.ComparatorType comparatorType = TermsFacet.ComparatorType.COUNT;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
fieldName = parser.currentName();
|
||||
|
@ -69,6 +70,8 @@ public class TermsFacetCollectorParser implements FacetCollectorParser {
|
|||
regex = parser.text();
|
||||
} else if ("regex_flags".equals(fieldName) || "regexFlags".equals(fieldName)) {
|
||||
regexFlags = parser.text();
|
||||
} else if ("order".equals(fieldName) || "comparator".equals(field)) {
|
||||
comparatorType = TermsFacet.ComparatorType.fromString(parser.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +79,6 @@ public class TermsFacetCollectorParser implements FacetCollectorParser {
|
|||
if (regex != null) {
|
||||
pattern = Regex.compile(regex, regexFlags);
|
||||
}
|
||||
return new TermsFacetCollector(facetName, field, size, context.numberOfShards(), context.fieldDataCache(), context.mapperService(), excluded, pattern);
|
||||
return new TermsFacetCollector(facetName, field, size, comparatorType, context.numberOfShards(), context.fieldDataCache(), context.mapperService(), excluded, pattern);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,6 +230,8 @@ public class SimpleFacetsTests extends AbstractNodesTests {
|
|||
assertThat(facet.entries().get(1).term(), anyOf(equalTo("xxx"), equalTo("zzz")));
|
||||
assertThat(facet.entries().get(1).count(), equalTo(1));
|
||||
|
||||
// Test Exclude
|
||||
|
||||
searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("facet1").field("tag").size(10).exclude("yyy"))
|
||||
|
@ -242,6 +244,23 @@ public class SimpleFacetsTests extends AbstractNodesTests {
|
|||
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 Order
|
||||
|
||||
searchResponse = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addFacet(termsFacet("facet1").field("tag").size(10).order(TermsFacet.ComparatorType.TERM))
|
||||
.execute().actionGet();
|
||||
|
||||
facet = searchResponse.facets().facet("facet1");
|
||||
assertThat(facet.name(), equalTo("facet1"));
|
||||
assertThat(facet.entries().size(), equalTo(3));
|
||||
assertThat(facet.entries().get(0).term(), equalTo("xxx"));
|
||||
assertThat(facet.entries().get(0).count(), equalTo(1));
|
||||
assertThat(facet.entries().get(1).term(), equalTo("yyy"));
|
||||
assertThat(facet.entries().get(1).count(), equalTo(2));
|
||||
assertThat(facet.entries().get(2).term(), equalTo("zzz"));
|
||||
assertThat(facet.entries().get(2).count(), equalTo(1));
|
||||
}
|
||||
|
||||
@Test public void testTermFacetWithEqualTermDistribution() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue