diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/MultiPhrasePrefixQuery.java b/core/src/main/java/org/elasticsearch/common/lucene/search/MultiPhrasePrefixQuery.java index 52de9a7e5db..05006ec0db7 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/MultiPhrasePrefixQuery.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/MultiPhrasePrefixQuery.java @@ -150,7 +150,7 @@ public class MultiPhrasePrefixQuery extends Query { } } if (terms.isEmpty()) { - return Queries.newMatchNoDocsQuery(); + return Queries.newMatchNoDocsQuery("No terms supplied for " + MultiPhrasePrefixQuery.class.getName()); } query.add(terms.toArray(Term.class), position); return query.build(); diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/Queries.java b/core/src/main/java/org/elasticsearch/common/lucene/search/Queries.java index 53ee2295ae4..c3144a7e372 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/Queries.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/Queries.java @@ -44,8 +44,8 @@ public class Queries { } /** Return a query that matches no document. */ - public static Query newMatchNoDocsQuery() { - return new BooleanQuery.Builder().build(); + public static Query newMatchNoDocsQuery(String reason) { + return new MatchNoDocsQuery(reason); } public static Query newNestedFilter() { diff --git a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java index b20d52b900e..b402f45bfdd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/internal/IndexFieldMapper.java @@ -144,7 +144,7 @@ public class IndexFieldMapper extends MetadataFieldMapper { if (isSameIndex(value, context.index().getName())) { return Queries.newMatchAllQuery(); } 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 - return Queries.newMatchNoDocsQuery(); + return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + values); } private boolean isSameIndex(Object value, String indexName) { diff --git a/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java index dec6baf067c..afcff164bec 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ExistsQueryBuilder.java @@ -134,7 +134,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder (FieldNamesFieldMapper.FieldNamesFieldType)context.getMapperService().fullName(FieldNamesFieldMapper.NAME); if (fieldNamesFieldType == null) { // 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 fields; diff --git a/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java index e8f1fb93b74..7845e2732ea 100644 --- a/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java @@ -204,7 +204,7 @@ public class IdsQueryBuilder extends AbstractQueryBuilder { protected Query doToQuery(QueryShardContext context) throws IOException { Query query; if (this.ids.isEmpty()) { - query = Queries.newMatchNoDocsQuery(); + query = Queries.newMatchNoDocsQuery("Missing ids in \"" + this.getName() + "\" query."); } else { Collection typesForQuery; if (types.length == 0) { diff --git a/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java index d17d8515bb8..068b0e86d8e 100644 --- a/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/MatchNoneQueryBuilder.java @@ -93,7 +93,7 @@ public class MatchNoneQueryBuilder extends AbstractQueryBuilder queryBuilder, final QueryShardContext context) throws IOException { final Query query = QueryBuilder.rewriteQuery(queryBuilder, context).toQuery(context); if (query == null) { - return Queries.newMatchNoDocsQuery(); + return Queries.newMatchNoDocsQuery("No query left after rewrite."); } return query; } diff --git a/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java index 19fe8da3011..084f2e766d4 100644 --- a/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java @@ -317,7 +317,7 @@ public class TermsQueryBuilder extends AbstractQueryBuilder { throw new UnsupportedOperationException("query must be rewritten first"); } if (values == null || values.isEmpty()) { - return Queries.newMatchNoDocsQuery(); + return Queries.newMatchNoDocsQuery("No terms supplied for \"" + getName() + "\" query."); } return handleTermsQuery(values, fieldName, context); } diff --git a/core/src/main/java/org/elasticsearch/index/search/MatchQuery.java b/core/src/main/java/org/elasticsearch/index/search/MatchQuery.java index 14b6e120fb7..0fbc17e3ae8 100644 --- a/core/src/main/java/org/elasticsearch/index/search/MatchQuery.java +++ b/core/src/main/java/org/elasticsearch/index/search/MatchQuery.java @@ -286,7 +286,11 @@ public class MatchQuery { } 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 { diff --git a/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java b/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java index a3004ba896c..ba55413a27b 100644 --- a/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java +++ b/core/src/test/java/org/elasticsearch/index/query/AbstractQueryTestCase.java @@ -24,7 +24,6 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.io.JsonStringEncoder; import org.apache.lucene.search.BoostQuery; -import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.spans.SpanBoostQuery; diff --git a/core/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java index 2fe7d3cfc0c..c7cfa4e0e1d 100644 --- a/core/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java @@ -21,16 +21,15 @@ package org.elasticsearch.index.query; import org.apache.lucene.queries.TermsQuery; -import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.ParsingException; +import org.elasticsearch.common.lucene.search.MatchNoDocsQuery; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; @@ -88,8 +87,7 @@ public class IdsQueryBuilderTests extends AbstractQueryTestCase @Override protected void doAssertLuceneQuery(IdsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException { if (queryBuilder.ids().size() == 0) { - assertThat(query, instanceOf(BooleanQuery.class)); - assertThat(((BooleanQuery)query).clauses().size(), equalTo(0)); + assertThat(query, instanceOf(MatchNoDocsQuery.class)); } else { assertThat(query, instanceOf(TermsQuery.class)); } diff --git a/core/src/test/java/org/elasticsearch/index/query/MatchNoneQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/MatchNoneQueryBuilderTests.java index 066db1aad45..e2ebbd8864d 100644 --- a/core/src/test/java/org/elasticsearch/index/query/MatchNoneQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/MatchNoneQueryBuilderTests.java @@ -19,12 +19,11 @@ package org.elasticsearch.index.query; -import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; +import org.elasticsearch.common.lucene.search.MatchNoDocsQuery; import java.io.IOException; -import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; public class MatchNoneQueryBuilderTests extends AbstractQueryTestCase { @@ -36,9 +35,7 @@ public class MatchNoneQueryBuilderTests extends AbstractQueryTestCase terms; - if (queryBuilder.termsLookup() != null) { - terms = randomTerms; + if (queryBuilder.termsLookup() == null && (queryBuilder.values() == null || queryBuilder.values().isEmpty())) { + assertThat(query, instanceOf(MatchNoDocsQuery.class)); } else { - terms = queryBuilder.values(); - } - - // compare whether we have the expected list of terms returned - final List 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 expectedTerms = new ArrayList<>(); - for (Object term : terms) { - if (term != null) { // terms lookup filters this out - expectedTerms.add(new Term(queryBuilder.fieldName(), term.toString())); + assertThat(query, instanceOf(BooleanQuery.class)); + BooleanQuery booleanQuery = (BooleanQuery) query; + + // 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 terms; + if (queryBuilder.termsLookup() != null) { + terms = randomTerms; + } else { + terms = queryBuilder.values(); + } + + // compare whether we have the expected list of terms returned + final List 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 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() {