Skip to content

Commit

Permalink
Search API: Query Facet - Add global flag to control if the facet is …
Browse files Browse the repository at this point in the history
…bounded to the search query or not, closes #50.
  • Loading branch information
kimchy committed Mar 5, 2010
1 parent 40b0dfd commit f4f26d2
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,22 @@ public SearchSourceFacetsBuilder facet(String name, JsonQueryBuilder query) {
if (queryFacets == null) {
queryFacets = newArrayListWithCapacity(2);
}
queryFacets.add(new FacetQuery(name, query));
queryFacets.add(new FacetQuery(name, query, null));
return this;
}

/**
* Adds a query facet (which results in a count facet returned) with an option to
* be global on the index or bounded by the search query.
*
* @param name The logical name of the facet, it will be returned under the name
* @param query The query facet
*/
public SearchSourceFacetsBuilder facet(String name, JsonQueryBuilder query, boolean global) {
if (queryFacets == null) {
queryFacets = newArrayListWithCapacity(2);
}
queryFacets.add(new FacetQuery(name, query, global));
return this;
}

Expand All @@ -78,6 +93,9 @@ public SearchSourceFacetsBuilder facet(String name, JsonQueryBuilder query) {
builder.startObject(facetQuery.name());
builder.field("query");
facetQuery.queryBuilder().toJson(builder, params);
if (facetQuery.global() != null) {
builder.field("global", facetQuery.global());
}
builder.endObject();
}
}
Expand All @@ -88,10 +106,12 @@ public SearchSourceFacetsBuilder facet(String name, JsonQueryBuilder query) {
private static class FacetQuery {
private final String name;
private final JsonQueryBuilder queryBuilder;
private final Boolean global;

private FacetQuery(String name, JsonQueryBuilder queryBuilder) {
private FacetQuery(String name, JsonQueryBuilder queryBuilder, Boolean global) {
this.name = name;
this.queryBuilder = queryBuilder;
this.global = global;
}

public String name() {
Expand All @@ -101,5 +121,9 @@ public String name() {
public JsonQueryBuilder queryBuilder() {
return queryBuilder;
}

public Boolean global() {
return this.global;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
* facets : {
* queryExecution : "collect|idset",
* facet1: {
* query : { ... }
* query : { ... },
* global : false
* }
* }
* </pre>
Expand All @@ -49,12 +50,12 @@ public class FacetsParseElement implements SearchParseElement {
JsonToken token;
SearchContextFacets.QueryExecutionType queryExecutionType = SearchContextFacets.QueryExecutionType.COLLECT;
List<SearchContextFacets.QueryFacet> queryFacets = null;
String topLevelFieldName = null;
while ((token = jp.nextToken()) != JsonToken.END_OBJECT) {
if (token == JsonToken.FIELD_NAME) {
String topLevelFieldName = jp.getCurrentName();

topLevelFieldName = jp.getCurrentName();
} else if (token == JsonToken.VALUE_STRING) {
if ("queryExecution".equals(topLevelFieldName)) {
jp.nextToken(); // move to value
String text = jp.getText();
if ("collect".equals(text)) {
queryExecutionType = SearchContextFacets.QueryExecutionType.COLLECT;
Expand All @@ -63,26 +64,36 @@ public class FacetsParseElement implements SearchParseElement {
} else {
throw new SearchParseException(context, "Unsupported query type [" + text + "]");
}
} else {

jp.nextToken(); // move to START_OBJECT

jp.nextToken(); // move to FIELD_NAME
String facetType = jp.getCurrentName();

if ("query".equals(facetType)) {
JsonIndexQueryParser indexQueryParser = (JsonIndexQueryParser) context.queryParser();
Query facetQuery = indexQueryParser.parse(jp);

if (queryFacets == null) {
queryFacets = Lists.newArrayListWithCapacity(2);
}
} else if (token == JsonToken.START_OBJECT) {
SearchContextFacets.Facet facet = null;
boolean global = false;
String facetFieldName = null;
while ((token = jp.nextToken()) != JsonToken.END_OBJECT) {
if (token == JsonToken.FIELD_NAME) {
facetFieldName = jp.getCurrentName();
} else if (token == JsonToken.START_OBJECT) {
if ("query".equals(facetFieldName)) {
JsonIndexQueryParser indexQueryParser = (JsonIndexQueryParser) context.queryParser();
Query facetQuery = indexQueryParser.parse(jp);
facet = new SearchContextFacets.QueryFacet(topLevelFieldName, facetQuery);
if (queryFacets == null) {
queryFacets = Lists.newArrayListWithCapacity(2);
}
queryFacets.add((SearchContextFacets.QueryFacet) facet);
}
queryFacets.add(new SearchContextFacets.QueryFacet(topLevelFieldName, facetQuery));
} else {
throw new SearchParseException(context, "Unsupported facet type [" + facetType + "] for facet name [" + topLevelFieldName + "]");
} else if (token == JsonToken.VALUE_TRUE) {
if ("global".equals(facetFieldName)) {
global = true;
}
} else if (token == JsonToken.VALUE_NUMBER_INT) {
global = jp.getIntValue() != 0;
}
jp.nextToken();
}
if (facet == null) {
throw new SearchParseException(context, "No facet type found for [" + topLevelFieldName + "]");
}
facet.global(global);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.QueryWrapperFilter;
import org.apache.lucene.search.*;
import org.apache.lucene.util.OpenBitSet;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.ElasticSearchIllegalStateException;
Expand All @@ -38,7 +36,7 @@
import java.util.Map;

/**
* @author kimchy (Shay Banon)
* @author kimchy (shay.banon)
*/
public class FacetsPhase implements SearchPhase {

Expand All @@ -63,17 +61,27 @@ public class FacetsPhase implements SearchPhase {
List<Facet> facets = Lists.newArrayListWithCapacity(2);
if (contextFacets.queryFacets() != null) {
for (SearchContextFacets.QueryFacet queryFacet : contextFacets.queryFacets()) {
Filter facetFilter = new QueryWrapperFilter(queryFacet.query());
facetFilter = context.filterCache().cache(facetFilter);
long count;
if (contextFacets.queryType() == SearchContextFacets.QueryExecutionType.COLLECT) {
count = executeQueryCollectorCount(context, queryFacet, facetFilter);
} else if (contextFacets.queryType() == SearchContextFacets.QueryExecutionType.IDSET) {
count = executeQueryIdSetCount(context, queryFacet, facetFilter);
if (queryFacet.global()) {
try {
Query globalQuery = new ConstantScoreQuery(context.filterCache().cache(new QueryWrapperFilter(queryFacet.query())));
long count = Lucene.count(context.searcher(), globalQuery, -1.0f);
facets.add(new CountFacet(queryFacet.name(), count));
} catch (Exception e) {
throw new FacetPhaseExecutionException(queryFacet.name(), "Failed to execute global facet [" + queryFacet.query() + "]", e);
}
} else {
throw new ElasticSearchIllegalStateException("No matching for type [" + contextFacets.queryType() + "]");
Filter facetFilter = new QueryWrapperFilter(queryFacet.query());
facetFilter = context.filterCache().cache(facetFilter);
long count;
if (contextFacets.queryType() == SearchContextFacets.QueryExecutionType.COLLECT) {
count = executeQueryCollectorCount(context, queryFacet, facetFilter);
} else if (contextFacets.queryType() == SearchContextFacets.QueryExecutionType.IDSET) {
count = executeQueryIdSetCount(context, queryFacet, facetFilter);
} else {
throw new ElasticSearchIllegalStateException("No matching for type [" + contextFacets.queryType() + "]");
}
facets.add(new CountFacet(queryFacet.name(), count));
}
facets.add(new CountFacet(queryFacet.name(), count));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import java.util.List;

/**
* @author kimchy (Shay Banon)
* @author kimchy (shay.banon)
*/
public class SearchContextFacets {

Expand All @@ -50,7 +50,22 @@ public List<QueryFacet> queryFacets() {
return queryFacets;
}

public static class QueryFacet {
public static abstract class Facet {
private boolean global;

protected Facet() {
}

public boolean global() {
return global;
}

public void global(boolean global) {
this.global = global;
}
}

public static class QueryFacet extends Facet {
private final String name;
private final Query query;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ protected Client getClient() {
SearchSourceBuilder sourceBuilder = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(20).explain(true)
.facets(facets().facet("all", termQuery("multi", "test")).facet("test1", termQuery("name", "test1")));
.facets(facets().facet("all", termQuery("multi", "test"), true).facet("test1", termQuery("name", "test1")));

SearchResponse searchResponse = client.search(searchRequest("test").source(sourceBuilder)).actionGet();
assertThat(searchResponse.hits().totalHits(), equalTo(100l));
Expand Down

0 comments on commit f4f26d2

Please sign in to comment.