Query DSL: Add different execution models for terms filter, closes #1568.
This commit is contained in:
parent
73b74847aa
commit
0ea58cacfd
|
@ -145,6 +145,28 @@ public class XBooleanFilter extends Filter {
|
|||
}
|
||||
}
|
||||
|
||||
public void addMust(Filter filter) {
|
||||
if (mustFilters == null) {
|
||||
mustFilters = new ArrayList<Filter>();
|
||||
}
|
||||
mustFilters.add(filter);
|
||||
}
|
||||
|
||||
public void addShould(Filter filter) {
|
||||
if (shouldFilters == null) {
|
||||
shouldFilters = new ArrayList<Filter>();
|
||||
}
|
||||
shouldFilters.add(filter);
|
||||
}
|
||||
|
||||
public void addNot(Filter filter) {
|
||||
if (notFilters == null) {
|
||||
notFilters = new ArrayList<Filter>();
|
||||
}
|
||||
notFilters.add(filter);
|
||||
}
|
||||
|
||||
|
||||
private boolean equalFilters(ArrayList<Filter> filters1, ArrayList<Filter> filters2) {
|
||||
return (filters1 == filters2) ||
|
||||
((filters1 != null) && filters1.equals(filters2));
|
||||
|
|
|
@ -25,8 +25,6 @@ import java.io.IOException;
|
|||
|
||||
/**
|
||||
* A filer for a field based on several terms matching on any of them.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TermsFilterBuilder extends BaseFilterBuilder {
|
||||
|
||||
|
@ -39,6 +37,8 @@ public class TermsFilterBuilder extends BaseFilterBuilder {
|
|||
|
||||
private String filterName;
|
||||
|
||||
private String execution;
|
||||
|
||||
/**
|
||||
* A filer for a field based on several terms matching on any of them.
|
||||
*
|
||||
|
@ -116,6 +116,15 @@ public class TermsFilterBuilder extends BaseFilterBuilder {
|
|||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the execution mode for the terms filter. Cane be either "plain", "bool"
|
||||
* "and". Defaults to "plain".
|
||||
*/
|
||||
public TermsFilterBuilder execution(String execution) {
|
||||
this.execution = execution;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filter name for the filter that can be used when searching for matched_filters per hit.
|
||||
*/
|
||||
|
@ -146,6 +155,10 @@ public class TermsFilterBuilder extends BaseFilterBuilder {
|
|||
}
|
||||
builder.endArray();
|
||||
|
||||
if (execution != null) {
|
||||
builder.field("execution", execution);
|
||||
}
|
||||
|
||||
if (filterName != null) {
|
||||
builder.field("_name", filterName);
|
||||
}
|
||||
|
|
|
@ -19,16 +19,21 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.PublicTermsFilter;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.AndFilter;
|
||||
import org.elasticsearch.common.lucene.search.TermFilter;
|
||||
import org.elasticsearch.common.lucene.search.XBooleanFilter;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.cache.filter.support.CacheKeyFilter;
|
||||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.index.query.support.QueryParsers.wrapSmartNameFilter;
|
||||
|
||||
|
@ -53,40 +58,31 @@ public class TermsFilterParser implements FilterParser {
|
|||
XContentParser parser = parseContext.parser();
|
||||
|
||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = null;
|
||||
boolean cache = true;
|
||||
PublicTermsFilter termsFilter = new PublicTermsFilter();
|
||||
Boolean cache = null;
|
||||
String filterName = null;
|
||||
String currentFieldName = null;
|
||||
CacheKeyFilter.Key cacheKey = null;
|
||||
XContentParser.Token token;
|
||||
String execution = "plain";
|
||||
List<String> terms = Lists.newArrayList();
|
||||
String fieldName = null;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||
String fieldName = currentFieldName;
|
||||
FieldMapper fieldMapper = null;
|
||||
smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||
if (smartNameFieldMappers != null) {
|
||||
if (smartNameFieldMappers.hasMapper()) {
|
||||
fieldMapper = smartNameFieldMappers.mapper();
|
||||
fieldName = fieldMapper.names().indexName();
|
||||
}
|
||||
}
|
||||
fieldName = currentFieldName;
|
||||
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
String value = parser.text();
|
||||
if (value == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
||||
}
|
||||
if (fieldMapper != null) {
|
||||
value = fieldMapper.indexedValue(value);
|
||||
termsFilter.addTerm(fieldMapper.names().createIndexNameTerm(value));
|
||||
} else {
|
||||
termsFilter.addTerm(new Term(fieldName, value));
|
||||
}
|
||||
terms.add(value);
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("_name".equals(currentFieldName)) {
|
||||
if ("execution".equals(currentFieldName)) {
|
||||
execution = parser.text();
|
||||
} else if ("_name".equals(currentFieldName)) {
|
||||
filterName = parser.text();
|
||||
} else if ("_cache".equals(currentFieldName)) {
|
||||
cache = parser.booleanValue();
|
||||
|
@ -96,9 +92,103 @@ public class TermsFilterParser implements FilterParser {
|
|||
}
|
||||
}
|
||||
|
||||
Filter filter = termsFilter;
|
||||
if (cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
if (fieldName == null) {
|
||||
throw new QueryParsingException(parseContext.index(), "bool filter requires a field name, followed by array of terms");
|
||||
}
|
||||
|
||||
FieldMapper fieldMapper = null;
|
||||
smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||
if (smartNameFieldMappers != null) {
|
||||
if (smartNameFieldMappers.hasMapper()) {
|
||||
fieldMapper = smartNameFieldMappers.mapper();
|
||||
fieldName = fieldMapper.names().indexName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Filter filter;
|
||||
if ("plain".equals(execution)) {
|
||||
PublicTermsFilter termsFilter = new PublicTermsFilter();
|
||||
if (fieldMapper != null) {
|
||||
for (String term : terms) {
|
||||
termsFilter.addTerm(fieldMapper.names().createIndexNameTerm(fieldMapper.indexedValue(term)));
|
||||
}
|
||||
} else {
|
||||
for (String term : terms) {
|
||||
termsFilter.addTerm(new Term(fieldName, term));
|
||||
}
|
||||
}
|
||||
filter = termsFilter;
|
||||
// cache the whole filter by default, or if explicitly told to
|
||||
if (cache == null || cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
}
|
||||
} else if ("bool".equals(execution)) {
|
||||
XBooleanFilter boolFiler = new XBooleanFilter();
|
||||
if (fieldMapper != null) {
|
||||
for (String term : terms) {
|
||||
boolFiler.addShould(parseContext.cacheFilter(fieldMapper.fieldFilter(term, parseContext), null));
|
||||
}
|
||||
} else {
|
||||
for (String term : terms) {
|
||||
boolFiler.addShould(parseContext.cacheFilter(new TermFilter(new Term(fieldName, term)), null));
|
||||
}
|
||||
}
|
||||
filter = boolFiler;
|
||||
// only cache if explicitly told to, since we cache inner filters
|
||||
if (cache != null && cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
}
|
||||
} else if ("bool_nocache".equals(execution)) {
|
||||
XBooleanFilter boolFiler = new XBooleanFilter();
|
||||
if (fieldMapper != null) {
|
||||
for (String term : terms) {
|
||||
boolFiler.addShould(fieldMapper.fieldFilter(term, parseContext));
|
||||
}
|
||||
} else {
|
||||
for (String term : terms) {
|
||||
boolFiler.addShould(new TermFilter(new Term(fieldName, term)));
|
||||
}
|
||||
}
|
||||
filter = boolFiler;
|
||||
// cache the whole filter by default, or if explicitly told to
|
||||
if (cache == null || cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
}
|
||||
} else if ("and".equals(execution)) {
|
||||
List<Filter> filters = Lists.newArrayList();
|
||||
if (fieldMapper != null) {
|
||||
for (String term : terms) {
|
||||
filters.add(parseContext.cacheFilter(fieldMapper.fieldFilter(term, parseContext), null));
|
||||
}
|
||||
} else {
|
||||
for (String term : terms) {
|
||||
filters.add(parseContext.cacheFilter(new TermFilter(new Term(fieldName, term)), null));
|
||||
}
|
||||
}
|
||||
filter = new AndFilter(filters);
|
||||
// only cache if explicitly told to, since we cache inner filters
|
||||
if (cache != null && cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
}
|
||||
} else if ("and_nocache".equals(execution)) {
|
||||
List<Filter> filters = Lists.newArrayList();
|
||||
if (fieldMapper != null) {
|
||||
for (String term : terms) {
|
||||
filters.add(fieldMapper.fieldFilter(term, parseContext));
|
||||
}
|
||||
} else {
|
||||
for (String term : terms) {
|
||||
filters.add(new TermFilter(new Term(fieldName, term)));
|
||||
}
|
||||
}
|
||||
filter = new AndFilter(filters);
|
||||
// cache the whole filter by default, or if explicitly told to
|
||||
if (cache == null || cache) {
|
||||
filter = parseContext.cacheFilter(filter, cacheKey);
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "bool filter execution value [" + execution + "] not supported");
|
||||
}
|
||||
|
||||
filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext);
|
||||
|
|
Loading…
Reference in New Issue