Merge pull request #18007 from MaineC/enhancement/switch_boolean_to_match_no_docs_query

Switches from empty boolean query to matchNoDocs
This commit is contained in:
Isabel Drost-Fromm 2016-04-28 13:13:51 +02:00
commit b8b5dc1cba
17 changed files with 63 additions and 58 deletions

View File

@ -150,7 +150,7 @@ public class MultiPhrasePrefixQuery extends Query {
} }
} }
if (terms.isEmpty()) { if (terms.isEmpty()) {
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("No terms supplied for " + MultiPhrasePrefixQuery.class.getName());
} }
query.add(terms.toArray(Term.class), position); query.add(terms.toArray(Term.class), position);
return query.build(); return query.build();

View File

@ -44,8 +44,8 @@ public class Queries {
} }
/** Return a query that matches no document. */ /** Return a query that matches no document. */
public static Query newMatchNoDocsQuery() { public static Query newMatchNoDocsQuery(String reason) {
return new BooleanQuery.Builder().build(); return new MatchNoDocsQuery(reason);
} }
public static Query newNestedFilter() { public static Query newNestedFilter() {

View File

@ -144,7 +144,7 @@ public class IndexFieldMapper extends MetadataFieldMapper {
if (isSameIndex(value, context.index().getName())) { if (isSameIndex(value, context.index().getName())) {
return Queries.newMatchAllQuery(); return Queries.newMatchAllQuery();
} else { } else {
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + value);
} }
} }
@ -161,7 +161,7 @@ public class IndexFieldMapper extends MetadataFieldMapper {
} }
} }
// None of the listed index names are this one // None of the listed index names are this one
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + values);
} }
private boolean isSameIndex(Object value, String indexName) { private boolean isSameIndex(Object value, String indexName) {

View File

@ -134,7 +134,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
(FieldNamesFieldMapper.FieldNamesFieldType)context.getMapperService().fullName(FieldNamesFieldMapper.NAME); (FieldNamesFieldMapper.FieldNamesFieldType)context.getMapperService().fullName(FieldNamesFieldMapper.NAME);
if (fieldNamesFieldType == null) { if (fieldNamesFieldType == null) {
// can only happen when no types exist, so no docs exist either // can only happen when no types exist, so no docs exist either
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("Missing types in \"" + NAME + "\" query.");
} }
final Collection<String> fields; final Collection<String> fields;

View File

@ -204,7 +204,7 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
protected Query doToQuery(QueryShardContext context) throws IOException { protected Query doToQuery(QueryShardContext context) throws IOException {
Query query; Query query;
if (this.ids.isEmpty()) { if (this.ids.isEmpty()) {
query = Queries.newMatchNoDocsQuery(); query = Queries.newMatchNoDocsQuery("Missing ids in \"" + this.getName() + "\" query.");
} else { } else {
Collection<String> typesForQuery; Collection<String> typesForQuery;
if (types.length == 0) { if (types.length == 0) {

View File

@ -93,7 +93,7 @@ public class MatchNoneQueryBuilder extends AbstractQueryBuilder<MatchNoneQueryBu
@Override @Override
protected Query doToQuery(QueryShardContext context) throws IOException { protected Query doToQuery(QueryShardContext context) throws IOException {
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("User requested \"" + this.getName() + "\" query.");
} }
@Override @Override

View File

@ -373,7 +373,7 @@ public class QueryShardContext extends QueryRewriteContext {
private static Query toQuery(final QueryBuilder<?> queryBuilder, final QueryShardContext context) throws IOException { private static Query toQuery(final QueryBuilder<?> queryBuilder, final QueryShardContext context) throws IOException {
final Query query = QueryBuilder.rewriteQuery(queryBuilder, context).toQuery(context); final Query query = QueryBuilder.rewriteQuery(queryBuilder, context).toQuery(context);
if (query == null) { if (query == null) {
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("No query left after rewrite.");
} }
return query; return query;
} }

View File

@ -317,7 +317,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
throw new UnsupportedOperationException("query must be rewritten first"); throw new UnsupportedOperationException("query must be rewritten first");
} }
if (values == null || values.isEmpty()) { if (values == null || values.isEmpty()) {
return Queries.newMatchNoDocsQuery(); return Queries.newMatchNoDocsQuery("No terms supplied for \"" + getName() + "\" query.");
} }
return handleTermsQuery(values, fieldName, context); return handleTermsQuery(values, fieldName, context);
} }

View File

@ -286,7 +286,11 @@ public class MatchQuery {
} }
protected Query zeroTermsQuery() { protected Query zeroTermsQuery() {
return zeroTermsQuery == DEFAULT_ZERO_TERMS_QUERY ? Queries.newMatchNoDocsQuery() : Queries.newMatchAllQuery(); if (zeroTermsQuery == DEFAULT_ZERO_TERMS_QUERY) {
return Queries.newMatchNoDocsQuery("Matching no documents because no terms present.");
}
return Queries.newMatchAllQuery();
} }
private class MatchQueryBuilder extends QueryBuilder { private class MatchQueryBuilder extends QueryBuilder {

View File

@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.io.JsonStringEncoder; import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.SpanBoostQuery; import org.apache.lucene.search.spans.SpanBoostQuery;

View File

@ -21,16 +21,15 @@ package org.elasticsearch.index.query;
import org.apache.lucene.queries.TermsQuery; import org.apache.lucene.queries.TermsQuery;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
@ -88,8 +87,7 @@ public class IdsQueryBuilderTests extends AbstractQueryTestCase<IdsQueryBuilder>
@Override @Override
protected void doAssertLuceneQuery(IdsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { protected void doAssertLuceneQuery(IdsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
if (queryBuilder.ids().size() == 0) { if (queryBuilder.ids().size() == 0) {
assertThat(query, instanceOf(BooleanQuery.class)); assertThat(query, instanceOf(MatchNoDocsQuery.class));
assertThat(((BooleanQuery)query).clauses().size(), equalTo(0));
} else { } else {
assertThat(query, instanceOf(TermsQuery.class)); assertThat(query, instanceOf(TermsQuery.class));
} }

View File

@ -19,12 +19,11 @@
package org.elasticsearch.index.query; package org.elasticsearch.index.query;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
public class MatchNoneQueryBuilderTests extends AbstractQueryTestCase<MatchNoneQueryBuilder> { public class MatchNoneQueryBuilderTests extends AbstractQueryTestCase<MatchNoneQueryBuilder> {
@ -36,9 +35,7 @@ public class MatchNoneQueryBuilderTests extends AbstractQueryTestCase<MatchNoneQ
@Override @Override
protected void doAssertLuceneQuery(MatchNoneQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { protected void doAssertLuceneQuery(MatchNoneQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
assertThat(query, instanceOf(BooleanQuery.class)); assertThat(query, instanceOf(MatchNoDocsQuery.class));
BooleanQuery booleanQuery = (BooleanQuery) query;
assertThat(booleanQuery.clauses().size(), equalTo(0));
} }
public void testFromJson() throws IOException { public void testFromJson() throws IOException {

View File

@ -23,6 +23,7 @@ import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery; import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import java.io.IOException; import java.io.IOException;
import static org.hamcrest.CoreMatchers.either; import static org.hamcrest.CoreMatchers.either;
@ -72,7 +73,7 @@ public class MatchPhrasePrefixQueryBuilderTests extends AbstractQueryTestCase<Ma
assertThat(query, notNullValue()); assertThat(query, notNullValue());
assertThat(query, assertThat(query,
either(instanceOf(BooleanQuery.class)).or(instanceOf(MultiPhrasePrefixQuery.class)) either(instanceOf(BooleanQuery.class)).or(instanceOf(MultiPhrasePrefixQuery.class))
.or(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class))); .or(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class)).or(instanceOf(MatchNoDocsQuery.class)));
} }
public void testIllegalValues() { public void testIllegalValues() {

View File

@ -24,6 +24,7 @@ import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import java.io.IOException; import java.io.IOException;
@ -68,7 +69,7 @@ public class MatchPhraseQueryBuilderTests extends AbstractQueryTestCase<MatchPhr
protected void doAssertLuceneQuery(MatchPhraseQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { protected void doAssertLuceneQuery(MatchPhraseQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
assertThat(query, notNullValue()); assertThat(query, notNullValue());
assertThat(query, either(instanceOf(BooleanQuery.class)).or(instanceOf(PhraseQuery.class)) assertThat(query, either(instanceOf(BooleanQuery.class)).or(instanceOf(PhraseQuery.class))
.or(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class))); .or(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class)).or(instanceOf(MatchNoDocsQuery.class)));
} }
public void testIllegalValues() { public void testIllegalValues() {

View File

@ -30,7 +30,7 @@ import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery; import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.Fuzziness;
@ -127,7 +127,7 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
switch (queryBuilder.type()) { switch (queryBuilder.type()) {
case BOOLEAN: case BOOLEAN:
assertThat(query, either(instanceOf(BooleanQuery.class)).or(instanceOf(ExtendedCommonTermsQuery.class)) assertThat(query, either(instanceOf(BooleanQuery.class)).or(instanceOf(ExtendedCommonTermsQuery.class))
.or(instanceOf(TermQuery.class)).or(instanceOf(FuzzyQuery.class)) .or(instanceOf(TermQuery.class)).or(instanceOf(FuzzyQuery.class)).or(instanceOf(MatchNoDocsQuery.class))
.or(instanceOf(LegacyNumericRangeQuery.class)).or(instanceOf(PointRangeQuery.class))); .or(instanceOf(LegacyNumericRangeQuery.class)).or(instanceOf(PointRangeQuery.class)));
break; break;
case PHRASE: case PHRASE:

View File

@ -27,12 +27,12 @@ import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.LegacyNumericRangeQuery; import org.apache.lucene.search.LegacyNumericRangeQuery;
import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PointRangeQuery; import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.lucene.all.AllTermQuery; import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery; import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.index.search.MatchQuery; import org.elasticsearch.index.search.MatchQuery;

View File

@ -31,6 +31,7 @@ import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.get.GetResult;
@ -93,41 +94,45 @@ public class TermsQueryBuilderTests extends AbstractQueryTestCase<TermsQueryBuil
@Override @Override
protected void doAssertLuceneQuery(TermsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { protected void doAssertLuceneQuery(TermsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
assertThat(query, instanceOf(BooleanQuery.class)); if (queryBuilder.termsLookup() == null && (queryBuilder.values() == null || queryBuilder.values().isEmpty())) {
BooleanQuery booleanQuery = (BooleanQuery) query; assertThat(query, instanceOf(MatchNoDocsQuery.class));
// we only do the check below for string fields (otherwise we'd have to decode the values)
if (queryBuilder.fieldName().equals(INT_FIELD_NAME) || queryBuilder.fieldName().equals(DOUBLE_FIELD_NAME)
|| queryBuilder.fieldName().equals(BOOLEAN_FIELD_NAME) || queryBuilder.fieldName().equals(DATE_FIELD_NAME)) {
return;
}
// expected returned terms depending on whether we have a terms query or a terms lookup query
List<Object> terms;
if (queryBuilder.termsLookup() != null) {
terms = randomTerms;
} else { } else {
terms = queryBuilder.values(); assertThat(query, instanceOf(BooleanQuery.class));
} BooleanQuery booleanQuery = (BooleanQuery) query;
// compare whether we have the expected list of terms returned // we only do the check below for string fields (otherwise we'd have to decode the values)
final List<Term> booleanTerms = new ArrayList<>(); if (queryBuilder.fieldName().equals(INT_FIELD_NAME) || queryBuilder.fieldName().equals(DOUBLE_FIELD_NAME)
for (BooleanClause booleanClause : booleanQuery) { || queryBuilder.fieldName().equals(BOOLEAN_FIELD_NAME) || queryBuilder.fieldName().equals(DATE_FIELD_NAME)) {
assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.SHOULD)); return;
assertThat(booleanClause.getQuery(), instanceOf(TermQuery.class));
Term term = ((TermQuery) booleanClause.getQuery()).getTerm();
booleanTerms.add(term);
}
CollectionUtil.timSort(booleanTerms);
List<Term> expectedTerms = new ArrayList<>();
for (Object term : terms) {
if (term != null) { // terms lookup filters this out
expectedTerms.add(new Term(queryBuilder.fieldName(), term.toString()));
} }
// expected returned terms depending on whether we have a terms query or a terms lookup query
List<Object> terms;
if (queryBuilder.termsLookup() != null) {
terms = randomTerms;
} else {
terms = queryBuilder.values();
}
// compare whether we have the expected list of terms returned
final List<Term> booleanTerms = new ArrayList<>();
for (BooleanClause booleanClause : booleanQuery) {
assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.SHOULD));
assertThat(booleanClause.getQuery(), instanceOf(TermQuery.class));
Term term = ((TermQuery) booleanClause.getQuery()).getTerm();
booleanTerms.add(term);
}
CollectionUtil.timSort(booleanTerms);
List<Term> expectedTerms = new ArrayList<>();
for (Object term : terms) {
if (term != null) { // terms lookup filters this out
expectedTerms.add(new Term(queryBuilder.fieldName(), term.toString()));
}
}
CollectionUtil.timSort(expectedTerms);
assertEquals(expectedTerms + " vs. " + booleanTerms, expectedTerms.size(), booleanTerms.size());
assertEquals(expectedTerms + " vs. " + booleanTerms, expectedTerms, booleanTerms);
} }
CollectionUtil.timSort(expectedTerms);
assertEquals(expectedTerms + " vs. " + booleanTerms, expectedTerms.size(), booleanTerms.size());
assertEquals(expectedTerms + " vs. " + booleanTerms, expectedTerms, booleanTerms);
} }
public void testEmtpyFieldName() { public void testEmtpyFieldName() {