support in compound queries / filter parsers for lower level ones returning null as the result of parsing the inner query / filter.

This commit is contained in:
Shay Banon 2012-05-21 21:43:17 +02:00
parent 4b5c89478c
commit 0998f3f8a6
26 changed files with 270 additions and 44 deletions

View File

@ -33,6 +33,7 @@ public class Queries {
// We don't use MatchAllDocsQuery, its slower than the one below ... (much slower)
public final static Query MATCH_ALL_QUERY = new DeletionAwareConstantScoreQuery(new MatchAllDocsFilter());
public final static Query NO_MATCH_QUERY = MatchNoDocsQuery.INSTANCE;
/**
* A match all docs filter. Note, requires no caching!.

View File

@ -51,6 +51,7 @@ public class AndFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
ArrayList<Filter> filters = newArrayList();
boolean filtersFound = false;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -60,7 +61,11 @@ public class AndFilterParser implements FilterParser {
XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.START_ARRAY) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
filtersFound = true;
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
@ -68,12 +73,20 @@ public class AndFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
if ("filters".equals(currentFieldName)) {
filtersFound = true;
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
} else {
filtersFound = true;
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
}
} else if (token.isValue()) {
@ -90,10 +103,14 @@ public class AndFilterParser implements FilterParser {
}
}
if (filters.isEmpty()) {
if (!filtersFound) {
throw new QueryParsingException(parseContext.index(), "[and] filter requires 'filters' to be set on it'");
}
if (filters.isEmpty()) {
return null;
}
// no need to cache this one
Filter filter = new AndFilter(filters);
if (cache) {

View File

@ -62,26 +62,44 @@ public class BoolFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("must".equals(currentFieldName)) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.MUST));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.MUST));
}
} else if ("must_not".equals(currentFieldName) || "mustNot".equals(currentFieldName)) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.MUST_NOT));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.MUST_NOT));
}
} else if ("should".equals(currentFieldName)) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.SHOULD));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.SHOULD));
}
} else {
throw new QueryParsingException(parseContext.index(), "[bool] filter does not support [" + currentFieldName + "]");
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("must".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.MUST));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.MUST));
}
}
} else if ("must_not".equals(currentFieldName) || "mustNot".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.MUST_NOT));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.MUST_NOT));
}
}
} else if ("should".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
boolFilter.add(new FilterClause(parseContext.parseInnerFilter(), BooleanClause.Occur.SHOULD));
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
boolFilter.add(new FilterClause(filter, BooleanClause.Occur.SHOULD));
}
}
} else {
throw new QueryParsingException(parseContext.index(), "[bool] filter does not support [" + currentFieldName + "]");
@ -99,6 +117,10 @@ public class BoolFilterParser implements FilterParser {
}
}
if (boolFilter.getMustFilters().isEmpty() && boolFilter.getNotFilters().isEmpty() && boolFilter.getShouldFilters().isEmpty()) {
return null;
}
Filter filter = boolFilter;
if (cache) {
filter = parseContext.cacheFilter(filter, cacheKey);

View File

@ -67,26 +67,44 @@ public class BoolQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("must".equals(currentFieldName)) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.MUST));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.MUST));
}
} else if ("must_not".equals(currentFieldName) || "mustNot".equals(currentFieldName)) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.MUST_NOT));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.MUST_NOT));
}
} else if ("should".equals(currentFieldName)) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.SHOULD));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.SHOULD));
}
} else {
throw new QueryParsingException(parseContext.index(), "[bool] query does not support [" + currentFieldName + "]");
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("must".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.MUST));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.MUST));
}
}
} else if ("must_not".equals(currentFieldName) || "mustNot".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.MUST_NOT));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.MUST_NOT));
}
}
} else if ("should".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
clauses.add(new BooleanClause(parseContext.parseInnerQuery(), BooleanClause.Occur.SHOULD));
Query query = parseContext.parseInnerQuery();
if (query != null) {
clauses.add(new BooleanClause(query, BooleanClause.Occur.SHOULD));
}
}
} else {
throw new QueryParsingException(parseContext.index(), "bool query does not support [" + currentFieldName + "]");
@ -106,6 +124,10 @@ public class BoolQueryParser implements QueryParser {
}
}
if (clauses.isEmpty()) {
return null;
}
if (clauses.size() == 1) {
BooleanClause clause = clauses.get(0);
if (clause.getOccur() == BooleanClause.Occur.MUST) {

View File

@ -47,7 +47,9 @@ public class BoostingQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query positiveQuery = null;
boolean positiveQueryFound = false;
Query negativeQuery = null;
boolean negativeQueryFound = false;
float boost = -1;
float negativeBoost = -1;
@ -59,8 +61,10 @@ public class BoostingQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("positive".equals(currentFieldName)) {
positiveQuery = parseContext.parseInnerQuery();
positiveQueryFound = true;
} else if ("negative".equals(currentFieldName)) {
negativeQuery = parseContext.parseInnerQuery();
negativeQueryFound = true;
} else {
throw new QueryParsingException(parseContext.index(), "[boosting] query does not support [" + currentFieldName + "]");
}
@ -75,16 +79,21 @@ public class BoostingQueryParser implements QueryParser {
}
}
if (positiveQuery == null) {
if (positiveQuery == null && !positiveQueryFound) {
throw new QueryParsingException(parseContext.index(), "[boosting] query requires 'positive' query to be set'");
}
if (negativeQuery == null) {
if (negativeQuery == null && !negativeQueryFound) {
throw new QueryParsingException(parseContext.index(), "[boosting] query requires 'negative' query to be set'");
}
if (negativeBoost == -1) {
throw new QueryParsingException(parseContext.index(), "[boosting] query requires 'negative_boost' to be set'");
}
// parsers returned null
if (positiveQuery == null || negativeQuery == null) {
return null;
}
BoostingQuery boostingQuery = new BoostingQuery(positiveQuery, negativeQuery, negativeBoost);
if (boost != -1) {
boostingQuery.setBoost(boost);

View File

@ -51,7 +51,9 @@ public class ConstantScoreQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Filter filter = null;
boolean filterFound = false;
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -64,8 +66,10 @@ public class ConstantScoreQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("filter".equals(currentFieldName)) {
filter = parseContext.parseInnerFilter();
filterFound = true;
} else if ("query".equals(currentFieldName)) {
query = parseContext.parseInnerQuery();
queryFound = true;
} else {
throw new QueryParsingException(parseContext.index(), "[constant_score] query does not support [" + currentFieldName + "]");
}
@ -81,10 +85,14 @@ public class ConstantScoreQueryParser implements QueryParser {
}
}
}
if (filter == null && query == null) {
if (!filterFound && !queryFound) {
throw new QueryParsingException(parseContext.index(), "[constant_score] requires either 'filter' or 'query' element");
}
if (query == null && filter == null) {
return null;
}
if (filter != null) {
// cache the filter if possible needed
if (cache) {

View File

@ -49,6 +49,7 @@ public class CustomBoostFactorQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
float boostFactor = 1.0f;
@ -60,6 +61,7 @@ public class CustomBoostFactorQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
query = parseContext.parseInnerQuery();
queryFound = true;
} else {
throw new QueryParsingException(parseContext.index(), "[custom_boost_factor] query does not support [" + currentFieldName + "]");
}
@ -73,9 +75,12 @@ public class CustomBoostFactorQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[constant_factor_query] requires 'query' element");
}
if (query == null) {
return null;
}
FunctionScoreQuery functionScoreQuery = new FunctionScoreQuery(query, new BoostScoreFunction(boostFactor));
functionScoreQuery.setBoost(boost);
return functionScoreQuery;

View File

@ -55,12 +55,14 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
String scriptLang = null;
Map<String, Object> vars = null;
FiltersFunctionScoreQuery.ScoreMode scoreMode = FiltersFunctionScoreQuery.ScoreMode.First;
ArrayList<Filter> filters = new ArrayList<Filter>();
boolean filtersFound = false;
ArrayList<String> scripts = new ArrayList<String>();
TFloatArrayList boosts = new TFloatArrayList();
@ -72,6 +74,7 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
query = parseContext.parseInnerQuery();
queryFound = true;
} else if ("params".equals(currentFieldName)) {
vars = parser.map();
} else {
@ -79,9 +82,11 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("filters".equals(currentFieldName)) {
filtersFound = true;
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
String script = null;
Filter filter = null;
boolean filterFound = false;
float fboost = Float.NaN;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
@ -89,6 +94,7 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("filter".equals(currentFieldName)) {
filter = parseContext.parseInnerFilter();
filterFound = true;
}
} else if (token.isValue()) {
if ("script".equals(currentFieldName)) {
@ -101,12 +107,14 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
if (script == null && fboost == -1) {
throw new QueryParsingException(parseContext.index(), "[custom_filters_score] missing 'script' or 'boost' in filters array element");
}
if (filter == null) {
if (!filterFound) {
throw new QueryParsingException(parseContext.index(), "[custom_filters_score] missing 'filter' in filters array element");
}
filters.add(filter);
scripts.add(script);
boosts.add(fboost);
if (filter != null) {
filters.add(filter);
scripts.add(script);
boosts.add(fboost);
}
}
} else {
throw new QueryParsingException(parseContext.index(), "[custom_filters_score] query does not support [" + currentFieldName + "]");
@ -138,12 +146,19 @@ public class CustomFiltersScoreQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[custom_filters_score] requires 'query' field");
}
if (filters.isEmpty()) {
if (query == null) {
return null;
}
if (!filtersFound) {
throw new QueryParsingException(parseContext.index(), "[custom_filters_score] requires 'filters' field");
}
// if all filter elements returned null, just use the query
if (filters.isEmpty()) {
return query;
}
FiltersFunctionScoreQuery.FilterFunction[] filterFunctions = new FiltersFunctionScoreQuery.FilterFunction[filters.size()];
for (int i = 0; i < filterFunctions.length; i++) {

View File

@ -53,6 +53,7 @@ public class CustomScoreQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
String script = null;
String scriptLang = null;
@ -66,6 +67,7 @@ public class CustomScoreQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
query = parseContext.parseInnerQuery();
queryFound = true;
} else if ("params".equals(currentFieldName)) {
vars = parser.map();
} else {
@ -83,12 +85,15 @@ public class CustomScoreQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[custom_score] requires 'query' field");
}
if (script == null) {
throw new QueryParsingException(parseContext.index(), "[custom_score] requires 'script' field");
}
if (query == null) {
return null;
}
SearchScript searchScript = parseContext.scriptService().search(parseContext.lookup(), scriptLang, script, vars);
FunctionScoreQuery functionScoreQuery = new FunctionScoreQuery(query, new ScriptScoreFunction(script, vars, searchScript));

View File

@ -54,6 +54,7 @@ public class DisMaxQueryParser implements QueryParser {
float tieBreaker = 0.0f;
List<Query> queries = newArrayList();
boolean queriesFound = false;
String currentFieldName = null;
XContentParser.Token token;
@ -62,14 +63,22 @@ public class DisMaxQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("queries".equals(currentFieldName)) {
queries.add(parseContext.parseInnerQuery());
queriesFound = true;
Query query = parseContext.parseInnerQuery();
if (query != null) {
queries.add(query);
}
} else {
throw new QueryParsingException(parseContext.index(), "[dis_max] query does not support [" + currentFieldName + "]");
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("queries".equals(currentFieldName)) {
queriesFound = true;
while (token != XContentParser.Token.END_ARRAY) {
queries.add(parseContext.parseInnerQuery());
Query query = parseContext.parseInnerQuery();
if (query != null) {
queries.add(query);
}
token = parser.nextToken();
}
} else {
@ -86,6 +95,14 @@ public class DisMaxQueryParser implements QueryParser {
}
}
if (!queriesFound) {
throw new QueryParsingException(parseContext.index(), "[dis_max] requires 'queries' field");
}
if (queries.isEmpty()) {
return null;
}
DisjunctionMaxQuery query = new DisjunctionMaxQuery(queries, tieBreaker);
query.setBoost(boost);
return query;

View File

@ -50,6 +50,7 @@ public class FQueryFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -61,6 +62,7 @@ public class FQueryFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
queryFound = true;
query = parseContext.parseInnerQuery();
} else {
throw new QueryParsingException(parseContext.index(), "[fquery] filter does not support [" + currentFieldName + "]");
@ -77,6 +79,12 @@ public class FQueryFilterParser implements FilterParser {
}
}
}
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[fquery] requires 'query' element");
}
if (query == null) {
return null;
}
Filter filter = new QueryWrapperFilter(query);
if (cache) {
filter = parseContext.cacheFilter(filter, cacheKey);

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.Filter;
import org.elasticsearch.common.Nullable;
import java.io.IOException;
@ -37,5 +38,6 @@ public interface FilterParser {
* Parses the into a filter from the current parser location. Will be at "START_OBJECT" location,
* and should end when the token is at the matching "END_OBJECT".
*/
@Nullable
Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException;
}

View File

@ -51,7 +51,9 @@ public class FilteredQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
Filter filter = null;
boolean filterFound = false;
float boost = 1.0f;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -63,8 +65,10 @@ public class FilteredQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
queryFound = true;
query = parseContext.parseInnerQuery();
} else if ("filter".equals(currentFieldName)) {
filterFound = true;
filter = parseContext.parseInnerFilter();
} else {
throw new QueryParsingException(parseContext.index(), "[filtered] query does not support [" + currentFieldName + "]");
@ -81,12 +85,21 @@ public class FilteredQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[filtered] requires 'query' element");
}
// we allow for null filter, so it makes compositions on the client side to be simpler
if (query == null) {
return null;
}
if (filter == null) {
return query;
if (!filterFound) {
// we allow for null filter, so it makes compositions on the client side to be simpler
return query;
} else {
// the filter was provided, but returned null, meaning we should discard it, this means no
// matches for this query...
return Queries.NO_MATCH_QUERY;
}
}
// cache if required

View File

@ -52,6 +52,7 @@ public class HasChildFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
String childType = null;
String scope = null;
@ -68,6 +69,7 @@ public class HasChildFilterParser implements FilterParser {
String[] origTypes = QueryParseContext.setTypesWithPrevious(childType == null ? null : new String[]{childType});
try {
query = parseContext.parseInnerQuery();
queryFound = true;
} finally {
QueryParseContext.setTypes(origTypes);
}
@ -86,9 +88,12 @@ public class HasChildFilterParser implements FilterParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[child] filter requires 'query' field");
}
if (query == null) {
return null;
}
if (childType == null) {
throw new QueryParsingException(parseContext.index(), "[child] filter requires 'type' field");
}

View File

@ -52,6 +52,7 @@ public class HasChildQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
String childType = null;
String scope = null;
@ -68,6 +69,7 @@ public class HasChildQueryParser implements QueryParser {
String[] origTypes = QueryParseContext.setTypesWithPrevious(childType == null ? null : new String[]{childType});
try {
query = parseContext.parseInnerQuery();
queryFound = true;
} finally {
QueryParseContext.setTypes(origTypes);
}
@ -86,9 +88,12 @@ public class HasChildQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[has_child] requires 'query' field");
}
if (query == null) {
return null;
}
if (childType == null) {
throw new QueryParsingException(parseContext.index(), "[has_child] requires 'type' field");
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.BytesStream;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
@ -232,12 +233,14 @@ public class IndexQueryParserService extends AbstractIndexComponent {
}
}
@Nullable
public Filter parseInnerFilter(XContentParser parser) throws IOException {
QueryParseContext context = cache.get();
context.reset(parser);
return context.parseInnerFilter();
}
@Nullable
public Query parseInnerQuery(XContentParser parser) throws IOException {
QueryParseContext context = cache.get();
context.reset(parser);
@ -247,6 +250,9 @@ public class IndexQueryParserService extends AbstractIndexComponent {
private ParsedQuery parse(QueryParseContext parseContext, XContentParser parser) throws IOException, QueryParsingException {
parseContext.reset(parser);
Query query = parseContext.parseInnerQuery();
if (query == null) {
query = Queries.NO_MATCH_QUERY;
}
return new ParsedQuery(query, parseContext.copyNamedFilters());
}

View File

@ -56,6 +56,7 @@ public class IndicesFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
Filter filter = null;
boolean filterFound = false;
Set<String> indices = Sets.newHashSet();
String currentFieldName = null;
@ -66,6 +67,7 @@ public class IndicesFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("filter".equals(currentFieldName)) {
filterFound = true;
filter = parseContext.parseInnerFilter();
} else if ("no_match_filter".equals(currentFieldName)) {
noMatchFilter = parseContext.parseInnerFilter();
@ -99,13 +101,17 @@ public class IndicesFilterParser implements FilterParser {
}
}
}
if (filter == null) {
if (!filterFound) {
throw new QueryParsingException(parseContext.index(), "[indices] requires 'filter' element");
}
if (indices.isEmpty()) {
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' element");
}
if (filter == null) {
return null;
}
String[] concreteIndices = indices.toArray(new String[indices.size()]);
if (clusterService != null) {
MetaData metaData = clusterService.state().metaData();

View File

@ -57,6 +57,7 @@ public class IndicesQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
Set<String> indices = Sets.newHashSet();
String currentFieldName = null;
@ -68,6 +69,7 @@ public class IndicesQueryParser implements QueryParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
query = parseContext.parseInnerQuery();
queryFound = true;
} else if ("no_match_query".equals(currentFieldName)) {
noMatchQuery = parseContext.parseInnerQuery();
} else {
@ -100,9 +102,12 @@ public class IndicesQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[indices] requires 'query' element");
}
if (query == null) {
return null;
}
if (indices.isEmpty()) {
throw new QueryParsingException(parseContext.index(), "[indices] requires 'indices' element");
}

View File

@ -50,7 +50,9 @@ public class NestedFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
Filter filter = null;
boolean filterFound = false;
float boost = 1.0f;
String scope = null;
String path = null;
@ -72,8 +74,10 @@ public class NestedFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
queryFound = true;
query = parseContext.parseInnerQuery();
} else if ("filter".equals(currentFieldName)) {
filterFound = true;
filter = parseContext.parseInnerFilter();
} else {
throw new QueryParsingException(parseContext.index(), "[nested] filter does not support [" + currentFieldName + "]");
@ -96,13 +100,17 @@ public class NestedFilterParser implements FilterParser {
}
}
}
if (query == null && filter == null) {
if (!queryFound && !filterFound) {
throw new QueryParsingException(parseContext.index(), "[nested] requires either 'query' or 'filter' field");
}
if (path == null) {
throw new QueryParsingException(parseContext.index(), "[nested] requires 'path' field");
}
if (query == null && filter == null) {
return null;
}
if (filter != null) {
query = new DeletionAwareConstantScoreQuery(filter);
}

View File

@ -50,7 +50,9 @@ public class NestedQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
Filter filter = null;
boolean filterFound = false;
float boost = 1.0f;
String scope = null;
String path = null;
@ -70,8 +72,10 @@ public class NestedQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
queryFound = true;
query = parseContext.parseInnerQuery();
} else if ("filter".equals(currentFieldName)) {
filterFound = true;
filter = parseContext.parseInnerFilter();
} else {
throw new QueryParsingException(parseContext.index(), "[nested] query does not support [" + currentFieldName + "]");
@ -101,13 +105,17 @@ public class NestedQueryParser implements QueryParser {
}
}
}
if (query == null && filter == null) {
if (!queryFound && !filterFound) {
throw new QueryParsingException(parseContext.index(), "[nested] requires either 'query' or 'filter' field");
}
if (path == null) {
throw new QueryParsingException(parseContext.index(), "[nested] requires 'path' field");
}
if (query == null && filter == null) {
return null;
}
if (filter != null) {
query = new DeletionAwareConstantScoreQuery(filter);
}

View File

@ -48,6 +48,7 @@ public class NotFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
Filter filter = null;
boolean filterFound = false;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -60,7 +61,9 @@ public class NotFilterParser implements FilterParser {
} else if (token == XContentParser.Token.START_OBJECT) {
if ("filter".equals(currentFieldName)) {
filter = parseContext.parseInnerFilter();
filterFound = true;
} else {
filterFound = true;
// its the filter, and the name is the field
filter = parseContext.parseInnerFilter(currentFieldName);
}
@ -77,10 +80,14 @@ public class NotFilterParser implements FilterParser {
}
}
if (filter == null) {
if (!filterFound) {
throw new QueryParsingException(parseContext.index(), "filter is required when using `not` filter");
}
if (filter == null) {
return null;
}
Filter notFilter = new NotFilter(filter);
if (cache) {
notFilter = parseContext.cacheFilter(notFilter, cacheKey);

View File

@ -51,6 +51,7 @@ public class OrFilterParser implements FilterParser {
XContentParser parser = parseContext.parser();
ArrayList<Filter> filters = newArrayList();
boolean filtersFound = false;
boolean cache = false;
CacheKeyFilter.Key cacheKey = null;
@ -60,7 +61,11 @@ public class OrFilterParser implements FilterParser {
XContentParser.Token token = parser.currentToken();
if (token == XContentParser.Token.START_ARRAY) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
filtersFound = true;
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
@ -68,12 +73,20 @@ public class OrFilterParser implements FilterParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
if ("filters".equals(currentFieldName)) {
filtersFound = true;
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
filters.add(parseContext.parseInnerFilter());
filtersFound = true;
Filter filter = parseContext.parseInnerFilter();
if (filter != null) {
filters.add(filter);
}
}
}
} else if (token.isValue()) {
@ -90,10 +103,14 @@ public class OrFilterParser implements FilterParser {
}
}
if (filters.isEmpty()) {
if (!filtersFound) {
throw new QueryParsingException(parseContext.index(), "[or] filter requires 'filters' to be set on it'");
}
if (filters.isEmpty()) {
return null;
}
// no need to cache this one
Filter filter = new OrFilter(filters);
if (cache) {

View File

@ -45,6 +45,9 @@ public class QueryFilterParser implements FilterParser {
@Override
public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
Query query = parseContext.parseInnerQuery();
if (query == null) {
return null;
}
return new QueryWrapperFilter(query);
}
}

View File

@ -160,6 +160,7 @@ public class QueryParseContext {
return ImmutableMap.copyOf(namedFilters);
}
@Nullable
public Query parseInnerQuery() throws IOException, QueryParsingException {
// move to START object
XContentParser.Token token;
@ -192,6 +193,7 @@ public class QueryParseContext {
return result;
}
@Nullable
public Filter parseInnerFilter() throws IOException, QueryParsingException {
// move to START object
XContentParser.Token token;

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.Nullable;
import java.io.IOException;
@ -36,6 +37,9 @@ public interface QueryParser {
/**
* Parses the into a query from the current parser location. Will be at "START_OBJECT" location,
* and should end when the token is at the matching "END_OBJECT".
* <p/>
* Returns <tt>null</tt> if this query should be ignored in the context of the DSL.
*/
@Nullable
Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException;
}

View File

@ -51,6 +51,7 @@ public class TopChildrenQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
Query query = null;
boolean queryFound = false;
float boost = 1.0f;
String childType = null;
String scope = null;
@ -65,6 +66,7 @@ public class TopChildrenQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
if ("query".equals(currentFieldName)) {
queryFound = true;
// TODO we need to set the type, but, `query` can come before `type`... (see HasChildFilterParser)
// since we switch types, make sure we change the context
String[] origTypes = QueryParseContext.setTypesWithPrevious(childType == null ? null : new String[]{childType});
@ -94,13 +96,17 @@ public class TopChildrenQueryParser implements QueryParser {
}
}
}
if (query == null) {
if (!queryFound) {
throw new QueryParsingException(parseContext.index(), "[child] requires 'query' field");
}
if (childType == null) {
throw new QueryParsingException(parseContext.index(), "[child] requires 'type' field");
}
if (query == null) {
return null;
}
DocumentMapper childDocMapper = parseContext.mapperService().documentMapper(childType);
if (childDocMapper == null) {
throw new QueryParsingException(parseContext.index(), "No mapping for for type [" + childType + "]");