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) {
|
private boolean equalFilters(ArrayList<Filter> filters1, ArrayList<Filter> filters2) {
|
||||||
return (filters1 == filters2) ||
|
return (filters1 == filters2) ||
|
||||||
((filters1 != null) && filters1.equals(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.
|
* A filer for a field based on several terms matching on any of them.
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class TermsFilterBuilder extends BaseFilterBuilder {
|
public class TermsFilterBuilder extends BaseFilterBuilder {
|
||||||
|
|
||||||
|
@ -39,6 +37,8 @@ public class TermsFilterBuilder extends BaseFilterBuilder {
|
||||||
|
|
||||||
private String filterName;
|
private String filterName;
|
||||||
|
|
||||||
|
private String execution;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A filer for a field based on several terms matching on any of them.
|
* 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;
|
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.
|
* 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();
|
builder.endArray();
|
||||||
|
|
||||||
|
if (execution != null) {
|
||||||
|
builder.field("execution", execution);
|
||||||
|
}
|
||||||
|
|
||||||
if (filterName != null) {
|
if (filterName != null) {
|
||||||
builder.field("_name", filterName);
|
builder.field("_name", filterName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,21 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.query;
|
package org.elasticsearch.index.query;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.search.Filter;
|
import org.apache.lucene.search.Filter;
|
||||||
import org.apache.lucene.search.PublicTermsFilter;
|
import org.apache.lucene.search.PublicTermsFilter;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
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.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.cache.filter.support.CacheKeyFilter;
|
import org.elasticsearch.index.cache.filter.support.CacheKeyFilter;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.FieldMapper;
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.elasticsearch.index.query.support.QueryParsers.wrapSmartNameFilter;
|
import static org.elasticsearch.index.query.support.QueryParsers.wrapSmartNameFilter;
|
||||||
|
|
||||||
|
@ -53,40 +58,31 @@ public class TermsFilterParser implements FilterParser {
|
||||||
XContentParser parser = parseContext.parser();
|
XContentParser parser = parseContext.parser();
|
||||||
|
|
||||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = null;
|
MapperService.SmartNameFieldMappers smartNameFieldMappers = null;
|
||||||
boolean cache = true;
|
Boolean cache = null;
|
||||||
PublicTermsFilter termsFilter = new PublicTermsFilter();
|
|
||||||
String filterName = null;
|
String filterName = null;
|
||||||
String currentFieldName = null;
|
String currentFieldName = null;
|
||||||
CacheKeyFilter.Key cacheKey = null;
|
CacheKeyFilter.Key cacheKey = null;
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
|
String execution = "plain";
|
||||||
|
List<String> terms = Lists.newArrayList();
|
||||||
|
String fieldName = null;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
} else if (token == XContentParser.Token.START_ARRAY) {
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
String fieldName = currentFieldName;
|
fieldName = currentFieldName;
|
||||||
FieldMapper fieldMapper = null;
|
|
||||||
smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
|
||||||
if (smartNameFieldMappers != null) {
|
|
||||||
if (smartNameFieldMappers.hasMapper()) {
|
|
||||||
fieldMapper = smartNameFieldMappers.mapper();
|
|
||||||
fieldName = fieldMapper.names().indexName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
String value = parser.text();
|
String value = parser.text();
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
throw new QueryParsingException(parseContext.index(), "No value specified for term filter");
|
||||||
}
|
}
|
||||||
if (fieldMapper != null) {
|
terms.add(value);
|
||||||
value = fieldMapper.indexedValue(value);
|
|
||||||
termsFilter.addTerm(fieldMapper.names().createIndexNameTerm(value));
|
|
||||||
} else {
|
|
||||||
termsFilter.addTerm(new Term(fieldName, value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (token.isValue()) {
|
} else if (token.isValue()) {
|
||||||
if ("_name".equals(currentFieldName)) {
|
if ("execution".equals(currentFieldName)) {
|
||||||
|
execution = parser.text();
|
||||||
|
} else if ("_name".equals(currentFieldName)) {
|
||||||
filterName = parser.text();
|
filterName = parser.text();
|
||||||
} else if ("_cache".equals(currentFieldName)) {
|
} else if ("_cache".equals(currentFieldName)) {
|
||||||
cache = parser.booleanValue();
|
cache = parser.booleanValue();
|
||||||
|
@ -96,10 +92,104 @@ public class TermsFilterParser implements FilterParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Filter filter = termsFilter;
|
if (fieldName == null) {
|
||||||
if (cache) {
|
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);
|
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);
|
filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext);
|
||||||
if (filterName != null) {
|
if (filterName != null) {
|
||||||
|
|
Loading…
Reference in New Issue