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:
kimchy 2010-08-08 09:31:40 +03:00
parent d4547c629f
commit 566ae94478
6 changed files with 92 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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