Remove the distinction between query and filter context in QueryBuilders (#35354)

When building a query Lucene distinguishes two cases, queries that require to produce a score and queries that only need to match. We cloned this mechanism in the QueryBuilders in order to be able to produce different queries based on whether they need to produce a score or not. However the only case in es that require this distinction is the BoolQueryBuilder that sets a different minimum_should_match when a `bool` query is built in a filter context..
This behavior doesn't seem right because it makes the matching of `should` clauses different when the score is not required.

Closes #35293
This commit is contained in:
Jim Ferenczi 2018-12-03 11:49:11 +01:00 committed by GitHub
parent 328d022ddd
commit 74aca756b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 26 additions and 314 deletions

View File

@ -159,3 +159,14 @@ Negative scores in the Function Score Query are deprecated in 6.x, and are
not allowed in this version. If a negative score is produced as a result
of computation (e.g. in `script_score` or `field_value_factor` functions),
an error will be thrown.
[float]
==== The filter context has been removed
The `filter` context has been removed from Elasticsearch's query builders,
the distinction between queries and filters is now decided in Lucene depending
on whether queries need to access score or not. As a result `bool` queries with
`should` clauses that don't need to access the score will no longer set their
`minimum_should_match` to 1. This behavior has been deprecated in the previous
major version.

View File

@ -17,15 +17,7 @@ contribute to the score.
in <<query-filter-context,filter context>>, meaning that scoring is ignored
and clauses are considered for caching.
|`should` |The clause (query) should appear in the matching document. If the
`bool` query is in a <<query-filter-context,query context>> and has a `must` or
`filter` clause then a document will match the `bool` query even if none of the
`should` queries match. In this case these clauses are only used to influence
the score. If the `bool` query is a <<query-filter-context,filter context>>
or has neither `must` or `filter` then at least one of the `should` queries
must match a document for it to match the `bool` query. This behavior may be
explicitly controlled by settings the
<<query-dsl-minimum-should-match,`minimum_should_match`>> parameter.
|`should` |The clause (query) should appear in the matching document.
|`must_not` |The clause (query) must not appear in the matching
documents. Clauses are executed in <<query-filter-context,filter context>> meaning
@ -33,13 +25,6 @@ that scoring is ignored and clauses are considered for caching. Because scoring
ignored, a score of `0` for all documents is returned.
|=======================================================================
[IMPORTANT]
.Bool query in filter context
========================================================================
If this query is used in a filter context and it has `should`
clauses then at least one `should` clause is required to match.
========================================================================
The `bool` query takes a _more-matches-is-better_ approach, so the score from
each matching `must` or `should` clause will be added together to provide the
final `_score` for each document.

View File

@ -139,6 +139,6 @@ public class AliasValidator {
private static void validateAliasFilter(XContentParser parser, QueryShardContext queryShardContext) throws IOException {
QueryBuilder parseInnerQueryBuilder = parseInnerQueryBuilder(parser);
QueryBuilder queryBuilder = Rewriteable.rewrite(parseInnerQueryBuilder, queryShardContext, true);
queryBuilder.toFilter(queryShardContext);
queryBuilder.toQuery(queryShardContext);
}
}

View File

@ -111,19 +111,6 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder<QB>>
return query;
}
@Override
public final Query toFilter(QueryShardContext context) throws IOException {
Query result;
final boolean originalIsFilter = context.isFilter();
try {
context.setIsFilter(true);
result = toQuery(context);
} finally {
context.setIsFilter(originalIsFilter);
}
return result;
}
protected abstract Query doToQuery(QueryShardContext context) throws IOException;
/**

View File

@ -384,12 +384,6 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
return new MatchAllDocsQuery();
}
final String minimumShouldMatch;
if (context.isFilter() && this.minimumShouldMatch == null && shouldClauses.size() > 0) {
minimumShouldMatch = "1";
} else {
minimumShouldMatch = this.minimumShouldMatch;
}
Query query = Queries.applyMinimumShouldMatch(booleanQuery, minimumShouldMatch);
return adjustPureNegative ? fixNegativeQueryIfNeeded(query) : query;
}
@ -397,17 +391,7 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
private static void addBooleanClauses(QueryShardContext context, BooleanQuery.Builder booleanQueryBuilder,
List<QueryBuilder> clauses, Occur occurs) throws IOException {
for (QueryBuilder query : clauses) {
Query luceneQuery = null;
switch (occurs) {
case MUST:
case SHOULD:
luceneQuery = query.toQuery(context);
break;
case FILTER:
case MUST_NOT:
luceneQuery = query.toFilter(context);
break;
}
Query luceneQuery = query.toQuery(context);
booleanQueryBuilder.add(new BooleanClause(luceneQuery, occurs));
}
}

View File

@ -129,7 +129,7 @@ public class ConstantScoreQueryBuilder extends AbstractQueryBuilder<ConstantScor
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
Query innerFilter = filterBuilder.toFilter(context);
Query innerFilter = filterBuilder.toQuery(context);
return new ConstantScoreQuery(innerFilter);
}

View File

@ -326,9 +326,6 @@ public class FuzzyQueryBuilder extends AbstractQueryBuilder<FuzzyQueryBuilder> i
protected Query doToQuery(QueryShardContext context) throws IOException {
Query query = null;
String rewrite = this.rewrite;
if (rewrite == null && context.isFilter()) {
rewrite = QueryParsers.CONSTANT_SCORE.getPreferredName();
}
MappedFieldType fieldType = context.fieldMapper(fieldName);
if (fieldType != null) {
query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions);

View File

@ -37,16 +37,6 @@ public interface QueryBuilder extends NamedWriteable, ToXContentObject, Rewritea
*/
Query toQuery(QueryShardContext context) throws IOException;
/**
* Converts this QueryBuilder to an unscored lucene {@link Query} that acts as a filter.
* Returns {@code null} if this query should be ignored in the context of
* parent queries.
*
* @param context additional information needed to construct the queries
* @return the {@link Query} or {@code null} if this query should be ignored upstream
*/
Query toFilter(QueryShardContext context) throws IOException;
/**
* Sets the arbitrary name to be assigned to the query (see named queries).
* Implementers should return the concrete type of the

View File

@ -97,7 +97,6 @@ public class QueryShardContext extends QueryRewriteContext {
private boolean allowUnmappedFields;
private boolean mapUnmappedFieldAsString;
private NestedScope nestedScope;
private boolean isFilter;
public QueryShardContext(int shardId, IndexSettings indexSettings, BitsetFilterCache bitsetFilterCache,
BiFunction<MappedFieldType, String, IndexFieldData<?>> indexFieldDataLookup, MapperService mapperService,
@ -132,7 +131,6 @@ public class QueryShardContext extends QueryRewriteContext {
this.lookup = null;
this.namedQueries.clear();
this.nestedScope = new NestedScope();
this.isFilter = false;
}
public IndexAnalyzers getIndexAnalyzers() {
@ -178,22 +176,6 @@ public class QueryShardContext extends QueryRewriteContext {
return unmodifiableMap(new HashMap<>(namedQueries));
}
/**
* Return whether we are currently parsing a filter or a query.
*/
public boolean isFilter() {
return isFilter;
}
/**
* Public for testing only!
*
* Sets whether we are currently parsing a filter or a query
*/
public void setIsFilter(boolean isFilter) {
this.isFilter = isFilter;
}
/**
* Returns all the fields that match a given pattern. If prefixed with a
* type then the fields will be returned with a type prefix.
@ -289,16 +271,6 @@ public class QueryShardContext extends QueryRewriteContext {
return indexSettings.getIndexVersionCreated();
}
public ParsedQuery toFilter(QueryBuilder queryBuilder) {
return toQuery(queryBuilder, q -> {
Query filter = q.toFilter(this);
if (filter == null) {
return null;
}
return filter;
});
}
public ParsedQuery toQuery(QueryBuilder queryBuilder) {
return toQuery(queryBuilder, q -> {
Query query = q.toQuery(this);

View File

@ -346,11 +346,6 @@ public class SpanNearQueryBuilder extends AbstractQueryBuilder<SpanNearQueryBuil
throw new UnsupportedOperationException();
}
@Override
public Query toFilter(QueryShardContext context) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public String queryName() {
throw new UnsupportedOperationException();

View File

@ -244,7 +244,7 @@ final class DefaultSearchContext extends SearchContext {
// initialize the filtering alias based on the provided filters
try {
final QueryBuilder queryBuilder = request.getAliasFilter().getQueryBuilder();
aliasFilter = queryBuilder == null ? null : queryBuilder.toFilter(queryShardContext);
aliasFilter = queryBuilder == null ? null : queryBuilder.toQuery(queryShardContext);
} catch (IOException e) {
throw new UncheckedIOException(e);
}

View File

@ -51,7 +51,7 @@ public class AdjacencyMatrixAggregatorFactory extends AggregatorFactory<Adjacenc
for (int i = 0; i < filters.size(); ++i) {
KeyedFilter keyedFilter = filters.get(i);
this.keys[i] = keyedFilter.key();
Query filter = keyedFilter.filter().toFilter(context.getQueryShardContext());
Query filter = keyedFilter.filter().toQuery(context.getQueryShardContext());
this.weights[i] = contextSearcher.createWeight(contextSearcher.rewrite(filter), ScoreMode.COMPLETE_NO_SCORES, 1f);
}
}

View File

@ -43,7 +43,7 @@ public class FilterAggregatorFactory extends AggregatorFactory<FilterAggregatorF
public FilterAggregatorFactory(String name, QueryBuilder filterBuilder, SearchContext context,
AggregatorFactory<?> parent, AggregatorFactories.Builder subFactoriesBuilder, Map<String, Object> metaData) throws IOException {
super(name, context, parent, subFactoriesBuilder, metaData);
filter = filterBuilder.toFilter(context.getQueryShardContext());
filter = filterBuilder.toQuery(context.getQueryShardContext());
}
/**

View File

@ -56,7 +56,7 @@ public class FiltersAggregatorFactory extends AggregatorFactory<FiltersAggregato
for (int i = 0; i < filters.size(); ++i) {
KeyedFilter keyedFilter = filters.get(i);
this.keys[i] = keyedFilter.key();
this.filters[i] = keyedFilter.filter().toFilter(context.getQueryShardContext());
this.filters[i] = keyedFilter.filter().toQuery(context.getQueryShardContext());
}
}

View File

@ -96,7 +96,7 @@ public class SignificantTermsAggregatorFactory extends ValuesSourceAggregatorFac
this.executionHint = executionHint;
this.filter = filterBuilder == null
? null
: filterBuilder.toFilter(context.getQueryShardContext());
: filterBuilder.toQuery(context.getQueryShardContext());
IndexSearcher searcher = context.searcher();
this.supersetNumDocs = filter == null
// Important - need to use the doc count that includes deleted docs

View File

@ -226,9 +226,9 @@ public abstract class SortBuilder<T extends SortBuilder<T>> implements NamedWrit
assert nestedFilter == Rewriteable.rewrite(nestedFilter, context) : "nested filter is not rewritten";
if (parentQuery == null) {
// this is for back-compat, original single level nested sorting never applied a nested type filter
childQuery = nestedFilter.toFilter(context);
childQuery = nestedFilter.toQuery(context);
} else {
childQuery = Queries.filtered(nestedObjectMapper.nestedTypeFilter(), nestedFilter.toFilter(context));
childQuery = Queries.filtered(nestedObjectMapper.nestedTypeFilter(), nestedFilter.toQuery(context));
}
} else {
childQuery = nestedObjectMapper.nestedTypeFilter();

View File

@ -21,7 +21,6 @@ package org.elasticsearch.index.query;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParsingException;
@ -41,7 +40,6 @@ import java.util.List;
import java.util.Map;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
@ -176,26 +174,6 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
}
}
public void testDefaultMinShouldMatch() throws Exception {
// Queries have a minShouldMatch of 0
BooleanQuery bq = (BooleanQuery) parseQuery(boolQuery().must(termQuery("foo", "bar"))).toQuery(createShardContext());
assertEquals(0, bq.getMinimumNumberShouldMatch());
bq = (BooleanQuery) parseQuery(boolQuery().should(termQuery("foo", "bar"))).toQuery(createShardContext());
assertEquals(0, bq.getMinimumNumberShouldMatch());
// Filters have a minShouldMatch of 0/1
ConstantScoreQuery csq = (ConstantScoreQuery) parseQuery(constantScoreQuery(boolQuery()
.must(termQuery("foo", "bar")))).toQuery(createShardContext());
bq = (BooleanQuery) csq.getQuery();
assertEquals(0, bq.getMinimumNumberShouldMatch());
csq = (ConstantScoreQuery) parseQuery(constantScoreQuery(boolQuery().should(termQuery("foo", "bar"))))
.toQuery(createShardContext());
bq = (BooleanQuery) csq.getQuery();
assertEquals(1, bq.getMinimumNumberShouldMatch());
}
public void testMinShouldMatchFilterWithoutShouldClauses() throws Exception {
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.filter(new BoolQueryBuilder().must(new MatchAllQueryBuilder()));
@ -216,29 +194,6 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
assertThat(innerBooleanClause.getQuery(), instanceOf(MatchAllDocsQuery.class));
}
public void testMinShouldMatchFilterWithShouldClauses() throws Exception {
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.filter(new BoolQueryBuilder().must(new MatchAllQueryBuilder()).should(new MatchAllQueryBuilder()));
Query query = boolQueryBuilder.toQuery(createShardContext());
assertThat(query, instanceOf(BooleanQuery.class));
BooleanQuery booleanQuery = (BooleanQuery) query;
assertThat(booleanQuery.getMinimumNumberShouldMatch(), equalTo(0));
assertThat(booleanQuery.clauses().size(), equalTo(1));
BooleanClause booleanClause = booleanQuery.clauses().get(0);
assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.FILTER));
assertThat(booleanClause.getQuery(), instanceOf(BooleanQuery.class));
BooleanQuery innerBooleanQuery = (BooleanQuery) booleanClause.getQuery();
//we didn't set minimum should match initially, but there are should clauses so it should be 1
assertThat(innerBooleanQuery.getMinimumNumberShouldMatch(), equalTo(1));
assertThat(innerBooleanQuery.clauses().size(), equalTo(2));
BooleanClause innerBooleanClause1 = innerBooleanQuery.clauses().get(0);
assertThat(innerBooleanClause1.getOccur(), equalTo(BooleanClause.Occur.MUST));
assertThat(innerBooleanClause1.getQuery(), instanceOf(MatchAllDocsQuery.class));
BooleanClause innerBooleanClause2 = innerBooleanQuery.clauses().get(1);
assertThat(innerBooleanClause2.getOccur(), equalTo(BooleanClause.Occur.SHOULD));
assertThat(innerBooleanClause2.getQuery(), instanceOf(MatchAllDocsQuery.class));
}
public void testMinShouldMatchBiggerThanNumberOfShouldClauses() throws Exception {
BooleanQuery bq = (BooleanQuery) parseQuery(
boolQuery()

View File

@ -114,11 +114,6 @@ public class SpanMultiTermQueryBuilderTests extends AbstractQueryTestCase<SpanMu
return new TermQuery(new Term("foo", "bar"));
}
@Override
public Query toFilter(QueryShardContext context) throws IOException {
return toQuery(context);
}
@Override
public QueryBuilder queryName(String queryName) {
return this;

View File

@ -19,10 +19,6 @@
package org.elasticsearch.index.query.plugin;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.indices.IndicesService;
@ -33,10 +29,7 @@ import org.junit.Before;
import java.util.Arrays;
import java.util.Collection;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.hamcrest.Matchers.instanceOf;
public class CustomQueryParserIT extends ESIntegTestCase {
@Override
@ -77,65 +70,4 @@ public class CustomQueryParserIT extends ESIntegTestCase {
return indicesService.indexServiceSafe(resolveIndex("index")).newQueryShardContext(
randomInt(20), null, () -> { throw new UnsupportedOperationException(); }, null);
}
//see #11120
public void testConstantScoreParsesFilter() throws Exception {
Query q = constantScoreQuery(new DummyQueryBuilder()).toQuery(queryShardContext());
Query inner = ((ConstantScoreQuery) q).getQuery();
assertThat(inner, instanceOf(DummyQueryParserPlugin.DummyQuery.class));
assertEquals(true, ((DummyQueryParserPlugin.DummyQuery) inner).isFilter);
}
//see #11120
public void testBooleanParsesFilter() throws Exception {
// single clause, serialized as inner object
Query q = boolQuery()
.should(new DummyQueryBuilder())
.must(new DummyQueryBuilder())
.filter(new DummyQueryBuilder())
.mustNot(new DummyQueryBuilder()).toQuery(queryShardContext());
assertThat(q, instanceOf(BooleanQuery.class));
BooleanQuery bq = (BooleanQuery) q;
assertEquals(4, bq.clauses().size());
for (BooleanClause clause : bq.clauses()) {
DummyQueryParserPlugin.DummyQuery dummy = (DummyQueryParserPlugin.DummyQuery) clause.getQuery();
switch (clause.getOccur()) {
case FILTER:
case MUST_NOT:
assertEquals(true, dummy.isFilter);
break;
case MUST:
case SHOULD:
assertEquals(false, dummy.isFilter);
break;
default:
throw new AssertionError();
}
}
// multiple clauses, serialized as inner arrays
q = boolQuery()
.should(new DummyQueryBuilder()).should(new DummyQueryBuilder())
.must(new DummyQueryBuilder()).must(new DummyQueryBuilder())
.filter(new DummyQueryBuilder()).filter(new DummyQueryBuilder())
.mustNot(new DummyQueryBuilder()).mustNot(new DummyQueryBuilder()).toQuery(queryShardContext());
assertThat(q, instanceOf(BooleanQuery.class));
bq = (BooleanQuery) q;
assertEquals(8, bq.clauses().size());
for (BooleanClause clause : bq.clauses()) {
DummyQueryParserPlugin.DummyQuery dummy = (DummyQueryParserPlugin.DummyQuery) clause.getQuery();
switch (clause.getOccur()) {
case FILTER:
case MUST_NOT:
assertEquals(true, dummy.isFilter);
break;
case MUST:
case SHOULD:
assertEquals(false, dummy.isFilter);
break;
default:
throw new AssertionError();
}
}
}
}

View File

@ -58,7 +58,7 @@ public class DummyQueryBuilder extends AbstractQueryBuilder<DummyQueryBuilder> {
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
return new DummyQuery(context.isFilter());
return new DummyQuery();
}
@Override
@ -75,4 +75,4 @@ public class DummyQueryBuilder extends AbstractQueryBuilder<DummyQueryBuilder> {
public String getWriteableName() {
return NAME;
}
}
}

View File

@ -40,13 +40,8 @@ public class DummyQueryParserPlugin extends Plugin implements SearchPlugin {
}
public static class DummyQuery extends Query {
public final boolean isFilter;
private final Query matchAllDocsQuery = new MatchAllDocsQuery();
public DummyQuery(boolean isFilter) {
this.isFilter = isFilter;
}
@Override
public String toString(String field) {
return getClass().getSimpleName();

View File

@ -23,24 +23,17 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.hamcrest.Matchers;
import org.junit.Before;
import java.io.IOException;
public class FilterAggregatorTests extends AggregatorTestCase {
private MappedFieldType fieldType;
@ -107,22 +100,4 @@ public class FilterAggregatorTests extends AggregatorTestCase {
indexReader.close();
directory.close();
}
public void testParsedAsFilter() throws IOException {
IndexReader indexReader = new MultiReader();
IndexSearcher indexSearcher = newSearcher(indexReader);
QueryBuilder filter = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("field", "foo"))
.should(QueryBuilders.termQuery("field", "bar"));
FilterAggregationBuilder builder = new FilterAggregationBuilder("test", filter);
AggregatorFactory<?> factory = createAggregatorFactory(builder, indexSearcher, fieldType);
assertThat(factory, Matchers.instanceOf(FilterAggregatorFactory.class));
FilterAggregatorFactory filterFactory = (FilterAggregatorFactory) factory;
Query parsedQuery = filterFactory.getWeight().getQuery();
assertThat(parsedQuery, Matchers.instanceOf(BooleanQuery.class));
assertEquals(2, ((BooleanQuery) parsedQuery).clauses().size());
// means the bool query has been parsed as a filter, if it was a query minShouldMatch would
// be 0
assertEquals(1, ((BooleanQuery) parsedQuery).getMinimumNumberShouldMatch());
}
}

View File

@ -23,23 +23,17 @@ import org.apache.lucene.document.Field;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.Directory;
import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.hamcrest.Matchers;
import org.junit.Before;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -203,22 +197,4 @@ public class FiltersAggregatorTests extends AggregatorTestCase {
indexReader.close();
directory.close();
}
public void testParsedAsFilter() throws IOException {
IndexReader indexReader = new MultiReader();
IndexSearcher indexSearcher = newSearcher(indexReader);
QueryBuilder filter = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("field", "foo"))
.should(QueryBuilders.termQuery("field", "bar"));
FiltersAggregationBuilder builder = new FiltersAggregationBuilder("test", filter);
AggregatorFactory<?> factory = createAggregatorFactory(builder, indexSearcher, fieldType);
assertThat(factory, Matchers.instanceOf(FiltersAggregatorFactory.class));
FiltersAggregatorFactory filtersFactory = (FiltersAggregatorFactory) factory;
Query parsedQuery = filtersFactory.getWeights()[0].getQuery();
assertThat(parsedQuery, Matchers.instanceOf(BooleanQuery.class));
assertEquals(2, ((BooleanQuery) parsedQuery).clauses().size());
// means the bool query has been parsed as a filter, if it was a query minShouldMatch would
// be 0
assertEquals(1, ((BooleanQuery) parsedQuery).getMinimumNumberShouldMatch());
}
}

View File

@ -28,11 +28,8 @@ import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.BytesRef;
@ -46,12 +43,9 @@ import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregatorFactory;
import org.elasticsearch.search.aggregations.AggregatorTestCase;
import org.elasticsearch.search.aggregations.bucket.significant.SignificantTermsAggregatorFactory.ExecutionMode;
import org.elasticsearch.search.aggregations.bucket.terms.IncludeExclude;
import org.elasticsearch.search.aggregations.support.ValueType;
import org.hamcrest.Matchers;
import org.junit.Before;
import java.io.IOException;
@ -86,28 +80,6 @@ public class SignificantTermsAggregatorTests extends AggregatorTestCase {
Function.identity()));
}
public void testParsedAsFilter() throws IOException {
IndexReader indexReader = new MultiReader();
IndexSearcher indexSearcher = newSearcher(indexReader);
QueryBuilder filter = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("field", "foo"))
.should(QueryBuilders.termQuery("field", "bar"));
SignificantTermsAggregationBuilder builder = new SignificantTermsAggregationBuilder(
"test", ValueType.STRING)
.field("field")
.backgroundFilter(filter);
AggregatorFactory<?> factory = createAggregatorFactory(builder, indexSearcher, fieldType);
assertThat(factory, Matchers.instanceOf(SignificantTermsAggregatorFactory.class));
SignificantTermsAggregatorFactory sigTermsFactory =
(SignificantTermsAggregatorFactory) factory;
Query parsedQuery = sigTermsFactory.filter;
assertThat(parsedQuery, Matchers.instanceOf(BooleanQuery.class));
assertEquals(2, ((BooleanQuery) parsedQuery).clauses().size());
// means the bool query has been parsed as a filter, if it was a query minShouldMatch would
// be 0
assertEquals(1, ((BooleanQuery) parsedQuery).getMinimumNumberShouldMatch());
}
/**
* Uses the significant terms aggregation to find the keywords in text fields
*/

View File

@ -76,7 +76,6 @@ import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.InternalAggregationTestCase;
import org.junit.After;
import org.mockito.Matchers;
import java.io.IOException;
import java.util.ArrayList;
@ -306,8 +305,6 @@ public abstract class AggregatorTestCase extends ESTestCase {
QueryShardContext queryShardContext = mock(QueryShardContext.class);
when(queryShardContext.getMapperService()).thenReturn(mapperService);
NestedScope nestedScope = new NestedScope();
when(queryShardContext.isFilter()).thenCallRealMethod();
Mockito.doCallRealMethod().when(queryShardContext).setIsFilter(Matchers.anyBoolean());
when(queryShardContext.nestedScope()).thenReturn(nestedScope);
return queryShardContext;
}

View File

@ -466,12 +466,6 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
assertNotEquals("modifying the boost doesn't affect the corresponding lucene query", rewrite(firstLuceneQuery),
rewrite(thirdLuceneQuery));
}
// check that context#isFilter is not changed by invoking toQuery/rewrite
boolean filterFlag = randomBoolean();
context.setIsFilter(filterFlag);
rewriteQuery(firstQuery, context).toQuery(context);
assertEquals("isFilter should be unchanged", filterFlag, context.isFilter());
}
}

View File

@ -136,7 +136,7 @@ public class SecurityIndexSearcherWrapper extends IndexSearcherWrapper {
QueryBuilder queryBuilder = queryShardContext.parseInnerQueryBuilder(parser);
verifyRoleQuery(queryBuilder);
failIfQueryUsesClient(queryBuilder, queryShardContext);
Query roleQuery = queryShardContext.toFilter(queryBuilder).query();
Query roleQuery = queryShardContext.toQuery(queryBuilder).query();
filter.add(roleQuery, SHOULD);
if (queryShardContext.getMapperService().hasNested()) {
NestedHelper nestedHelper = new NestedHelper(queryShardContext.getMapperService());

View File

@ -142,7 +142,7 @@ public class SecurityIndexSearcherWrapperIntegrationTests extends ESTestCase {
for (int i = 0; i < numValues; i++) {
ParsedQuery parsedQuery = new ParsedQuery(new TermQuery(new Term("field", values[i])));
doReturn(new TermQueryBuilder("field", values[i])).when(queryShardContext).parseInnerQueryBuilder(any(XContentParser.class));
when(queryShardContext.toFilter(new TermsQueryBuilder("field", values[i]))).thenReturn(parsedQuery);
when(queryShardContext.toQuery(new TermsQueryBuilder("field", values[i]))).thenReturn(parsedQuery);
DirectoryReader wrappedDirectoryReader = wrapper.wrap(directoryReader);
IndexSearcher indexSearcher = wrapper.wrap(new IndexSearcher(wrappedDirectoryReader));