diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java
index be7373adb0da3..bc0e04ed42bcb 100644
--- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java
+++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java
@@ -23,6 +23,7 @@
import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
@@ -75,6 +76,7 @@
import org.elasticsearch.index.query.QueryRewriteContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException;
+import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.indices.breaker.NoneCircuitBreakerService;
@@ -562,9 +564,9 @@ protected Analyzer getWrappedAnalyzer(String fieldName) {
PercolatorFieldMapper.FieldType pft = (PercolatorFieldMapper.FieldType) fieldType;
String name = this.name != null ? this.name : pft.name();
QueryShardContext percolateShardContext = wrap(context);
+ PercolatorFieldMapper.configureContext(percolateShardContext, pft.mapUnmappedFieldsAsText);;
PercolateQuery.QueryStore queryStore = createStore(pft.queryBuilderField,
- percolateShardContext,
- pft.mapUnmappedFieldsAsText);
+ percolateShardContext);
return pft.percolateQuery(name, queryStore, documents, docSearcher, excludeNestedDocuments, context.indexVersionCreated());
}
@@ -607,8 +609,7 @@ static IndexSearcher createMultiDocumentSearcher(Analyzer analyzer, Collection
{
@@ -634,7 +635,8 @@ static PercolateQuery.QueryStore createStore(MappedFieldType queryBuilderFieldTy
assert valueLength > 0;
QueryBuilder queryBuilder = input.readNamedWriteable(QueryBuilder.class);
assert in.read() == -1;
- return PercolatorFieldMapper.toQuery(context, mapUnmappedFieldsAsString, queryBuilder);
+ queryBuilder = Rewriteable.rewrite(queryBuilder, context);
+ return queryBuilder.toQuery(context);
}
}
} else {
@@ -647,6 +649,13 @@ static PercolateQuery.QueryStore createStore(MappedFieldType queryBuilderFieldTy
static QueryShardContext wrap(QueryShardContext shardContext) {
return new QueryShardContext(shardContext) {
+ @Override
+ public IndexReader getIndexReader() {
+ // The reader that matters in this context is not the reader of the shard but
+ // the reader of the MemoryIndex. We just use `null` for simplicity.
+ return null;
+ }
+
@Override
public BitSetProducer bitsetFilter(Query query) {
return context -> {
diff --git a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java
index e22eed78a6a52..bf481e23e1081 100644
--- a/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java
+++ b/modules/percolator/src/main/java/org/elasticsearch/percolator/PercolatorFieldMapper.java
@@ -394,6 +394,8 @@ public void parse(ParseContext context) throws IOException {
throw new IllegalArgumentException("a document can only contain one percolator query");
}
+ configureContext(queryShardContext, isMapUnmappedFieldAsText());
+
XContentParser parser = context.parser();
QueryBuilder queryBuilder = parseQueryBuilder(
parser, parser.getTokenLocation()
@@ -407,7 +409,8 @@ public void parse(ParseContext context) throws IOException {
Version indexVersion = context.mapperService().getIndexSettings().getIndexVersionCreated();
createQueryBuilderField(indexVersion, queryBuilderField, queryBuilder, context);
- Query query = toQuery(queryShardContext, isMapUnmappedFieldAsText(), queryBuilder);
+ QueryBuilder queryBuilderForProcessing = queryBuilder.rewrite(new QueryShardContext(queryShardContext));
+ Query query = queryBuilderForProcessing.toQuery(queryShardContext);
processQuery(query, context);
}
@@ -465,11 +468,7 @@ void processQuery(Query query, ParseContext context) {
doc.add(new NumericDocValuesField(minimumShouldMatchFieldMapper.name(), result.minimumShouldMatch));
}
- static Query parseQuery(QueryShardContext context, boolean mapUnmappedFieldsAsString, XContentParser parser) throws IOException {
- return toQuery(context, mapUnmappedFieldsAsString, parseQueryBuilder(parser, parser.getTokenLocation()));
- }
-
- static Query toQuery(QueryShardContext context, boolean mapUnmappedFieldsAsString, QueryBuilder queryBuilder) throws IOException {
+ static void configureContext(QueryShardContext context, boolean mapUnmappedFieldsAsString) {
// This means that fields in the query need to exist in the mapping prior to registering this query
// The reason that this is required, is that if a field doesn't exist then the query assumes defaults, which may be undesired.
//
@@ -484,7 +483,6 @@ static Query toQuery(QueryShardContext context, boolean mapUnmappedFieldsAsStrin
// as an analyzed string.
context.setAllowUnmappedFields(false);
context.setMapUnmappedFieldAsString(mapUnmappedFieldsAsString);
- return queryBuilder.toQuery(context);
}
private static QueryBuilder parseQueryBuilder(XContentParser parser, XContentLocation location) {
diff --git a/modules/percolator/src/test/java/org/elasticsearch/percolator/QueryBuilderStoreTests.java b/modules/percolator/src/test/java/org/elasticsearch/percolator/QueryBuilderStoreTests.java
index 88c2a098deb21..d9d920ae14d4d 100644
--- a/modules/percolator/src/test/java/org/elasticsearch/percolator/QueryBuilderStoreTests.java
+++ b/modules/percolator/src/test/java/org/elasticsearch/percolator/QueryBuilderStoreTests.java
@@ -38,10 +38,12 @@
import org.elasticsearch.index.fielddata.plain.BytesBinaryDVIndexFieldData;
import org.elasticsearch.index.mapper.BinaryFieldMapper;
import org.elasticsearch.index.mapper.ContentPath;
+import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.TermQueryBuilder;
+import org.elasticsearch.mock.orig.Mockito;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.test.ESTestCase;
@@ -93,7 +95,14 @@ public void testStoringQueryBuilders() throws IOException {
when(queryShardContext.getXContentRegistry()).thenReturn(xContentRegistry());
when(queryShardContext.getForField(fieldMapper.fieldType()))
.thenReturn(new BytesBinaryDVIndexFieldData(new Index("index", "uuid"), fieldMapper.name()));
- PercolateQuery.QueryStore queryStore = PercolateQueryBuilder.createStore(fieldMapper.fieldType(), queryShardContext, false);
+ when(queryShardContext.fieldMapper(Mockito.anyString())).thenAnswer(invocation -> {
+ final String fieldName = (String) invocation.getArguments()[0];
+ KeywordFieldMapper.KeywordFieldType ft = new KeywordFieldMapper.KeywordFieldType();
+ ft.setName(fieldName);
+ ft.freeze();
+ return ft;
+ });
+ PercolateQuery.QueryStore queryStore = PercolateQueryBuilder.createStore(fieldMapper.fieldType(), queryShardContext);
try (IndexReader indexReader = DirectoryReader.open(directory)) {
LeafReaderContext leafContext = indexReader.leaves().get(0);
diff --git a/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java
new file mode 100644
index 0000000000000..779e8f91350dc
--- /dev/null
+++ b/server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.index.mapper;
+
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.BytesRef;
+import org.elasticsearch.common.Nullable;
+import org.elasticsearch.common.lucene.search.Queries;
+import org.elasticsearch.common.regex.Regex;
+import org.elasticsearch.index.query.QueryShardContext;
+
+import java.util.List;
+
+/**
+ * A {@link MappedFieldType} that has the same value for all documents.
+ * Factory methods for queries are called at rewrite time so they should be
+ * cheap. In particular they should not read data from disk or perform a
+ * network call. Furthermore they may only return a {@link MatchAllDocsQuery}
+ * or a {@link MatchNoDocsQuery}.
+ */
+public abstract class ConstantFieldType extends MappedFieldType {
+
+ public ConstantFieldType() {
+ super();
+ }
+
+ public ConstantFieldType(ConstantFieldType other) {
+ super(other);
+ }
+
+ @Override
+ public final boolean isSearchable() {
+ return true;
+ }
+
+ @Override
+ public final boolean isAggregatable() {
+ return true;
+ }
+
+ @Override
+ public final Query existsQuery(QueryShardContext context) {
+ return new MatchAllDocsQuery();
+ }
+
+ /**
+ * Return whether the constant value of this field matches the provided {@code pattern}
+ * as documented in {@link Regex#simpleMatch}.
+ */
+ protected abstract boolean matches(String pattern, QueryShardContext context);
+
+ private static String valueToString(Object value) {
+ return value instanceof BytesRef
+ ? ((BytesRef) value).utf8ToString()
+ : value.toString();
+ }
+
+ @Override
+ public final Query termQuery(Object value, QueryShardContext context) {
+ String pattern = valueToString(value);
+ if (matches(pattern, context)) {
+ return Queries.newMatchAllQuery();
+ } else {
+ return new MatchNoDocsQuery();
+ }
+ }
+
+ @Override
+ public final Query termsQuery(List> values, QueryShardContext context) {
+ for (Object value : values) {
+ String pattern = valueToString(value);
+ if (matches(pattern, context)) {
+ // `terms` queries are a disjunction, so one matching term is enough
+ return Queries.newMatchAllQuery();
+ }
+ }
+ return new MatchNoDocsQuery();
+ }
+
+ @Override
+ public final Query prefixQuery(String prefix,
+ @Nullable MultiTermQuery.RewriteMethod method,
+ QueryShardContext context) {
+ String pattern = prefix + "*";
+ if (matches(pattern, context)) {
+ return Queries.newMatchAllQuery();
+ } else {
+ return new MatchNoDocsQuery();
+ }
+ }
+
+ @Override
+ public final Query wildcardQuery(String value,
+ @Nullable MultiTermQuery.RewriteMethod method,
+ QueryShardContext context) {
+ if (matches(value, context)) {
+ return Queries.newMatchAllQuery();
+ } else {
+ return new MatchNoDocsQuery();
+ }
+ }
+
+}
diff --git a/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java
index 88282fa685728..06dfe1bf273e2 100644
--- a/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java
+++ b/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java
@@ -21,13 +21,7 @@
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.MultiTermQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.util.BytesRef;
-import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.lucene.Lucene;
-import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.fielddata.IndexFieldData;
@@ -91,7 +85,7 @@ public MetadataFieldMapper getDefault(ParserContext context) {
}
}
- static final class IndexFieldType extends MappedFieldType {
+ static final class IndexFieldType extends ConstantFieldType {
IndexFieldType() {}
@@ -110,81 +104,8 @@ public String typeName() {
}
@Override
- public boolean isSearchable() {
- // The _index field is always searchable.
- return true;
- }
-
- @Override
- public Query existsQuery(QueryShardContext context) {
- return new MatchAllDocsQuery();
- }
-
- /**
- * This termQuery impl looks at the context to determine the index that
- * is being queried and then returns a MATCH_ALL_QUERY or MATCH_NO_QUERY
- * if the value matches this index. This can be useful if aliases or
- * wildcards are used but the aim is to restrict the query to specific
- * indices
- */
- @Override
- public Query termQuery(Object value, @Nullable QueryShardContext context) {
- String pattern = value instanceof BytesRef
- ? ((BytesRef) value).utf8ToString()
- : value.toString();
- if (context.indexMatches(pattern)) {
- // No need to OR these clauses - we can only logically be
- // running in the context of just one of these index names.
- return Queries.newMatchAllQuery();
- } else {
- return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
- "] doesn't match the provided value [" + value + "].");
- }
- }
-
- @Override
- public Query termsQuery(List values, QueryShardContext context) {
- if (context == null) {
- return super.termsQuery(values, context);
- }
- for (Object value : values) {
- String pattern = value instanceof BytesRef
- ? ((BytesRef) value).utf8ToString()
- : value.toString();
- if (context.indexMatches(pattern)) {
- // No need to OR these clauses - we can only logically be
- // running in the context of just one of these index names.
- return Queries.newMatchAllQuery();
- }
- }
- // None of the listed index names are this one
- return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
- "] doesn't match the provided values [" + values + "].");
- }
-
- @Override
- public Query prefixQuery(String value,
- @Nullable MultiTermQuery.RewriteMethod method,
- QueryShardContext context) {
- String pattern = value + "*";
- if (context.indexMatches(pattern)) {
- return Queries.newMatchAllQuery();
- } else {
- return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName() +
- "] doesn't match the provided prefix [" + value + "].");
- }
- }
-
- @Override
- public Query wildcardQuery(String value,
- @Nullable MultiTermQuery.RewriteMethod method,
- QueryShardContext context) {
- if (context.indexMatches(value)) {
- return Queries.newMatchAllQuery();
- } else {
- return Queries.newMatchNoDocsQuery("The index [" + context.getFullyQualifiedIndex().getName()
- + "] doesn't match the provided pattern [" + value + "].");
- }
+ protected boolean matches(String pattern, QueryShardContext context) {
+ return context.indexMatches(pattern);
}
@Override
diff --git a/server/src/main/java/org/elasticsearch/index/query/AbstractQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/AbstractQueryBuilder.java
index d5cc101ede8ad..2e027e21b8f5f 100644
--- a/server/src/main/java/org/elasticsearch/index/query/AbstractQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/AbstractQueryBuilder.java
@@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.BoostQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanQuery;
@@ -103,7 +104,7 @@ public final Query toQuery(QueryShardContext context) throws IOException {
if (boost != DEFAULT_BOOST) {
if (query instanceof SpanQuery) {
query = new SpanBoostQuery((SpanQuery) query, boost);
- } else {
+ } else if (query instanceof MatchNoDocsQuery == false) {
query = new BoostQuery(query, boost);
}
}
@@ -232,7 +233,7 @@ static Collection toQueries(Collection queryBuilders, Query
IOException {
List queries = new ArrayList<>(queryBuilders.size());
for (QueryBuilder queryBuilder : queryBuilders) {
- Query query = queryBuilder.toQuery(context);
+ Query query = queryBuilder.rewrite(context).toQuery(context);
if (query != null) {
queries.add(query);
}
diff --git a/server/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java
index 8df0fec044124..bd3048da29bb4 100644
--- a/server/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/FuzzyQueryBuilder.java
@@ -19,7 +19,6 @@
package org.elasticsearch.index.query;
-import org.apache.lucene.index.Term;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
@@ -28,7 +27,6 @@
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -322,18 +320,26 @@ public String getWriteableName() {
return NAME;
}
+ @Override
+ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null) {
+ MappedFieldType fieldType = context.fieldMapper(fieldName);
+ if (fieldType == null) {
+ return new MatchNoneQueryBuilder();
+ }
+ }
+ return super.doRewrite(context);
+ }
+
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
- Query query = null;
- String rewrite = this.rewrite;
MappedFieldType fieldType = context.fieldMapper(fieldName);
- if (fieldType != null) {
- query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions, context);
- }
- if (query == null) {
- int maxEdits = fuzziness.asDistance(BytesRefs.toString(value));
- query = new FuzzyQuery(new Term(fieldName, BytesRefs.toBytesRef(value)), maxEdits, prefixLength, maxExpansions, transpositions);
+ if (fieldType == null) {
+ throw new IllegalStateException("Rewrite first");
}
+ String rewrite = this.rewrite;
+ Query query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions, context);
if (query instanceof MultiTermQuery) {
MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(rewrite, null,
LoggingDeprecationHandler.INSTANCE);
diff --git a/server/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java
index 03a3fdfd646e6..721201cda094e 100644
--- a/server/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/IdsQueryBuilder.java
@@ -19,7 +19,6 @@
package org.elasticsearch.index.query;
-import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.Version;
import org.elasticsearch.common.ParseField;
@@ -27,7 +26,6 @@
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@@ -136,17 +134,26 @@ public String getWriteableName() {
return NAME;
}
+ @Override
+ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
+ if (ids.isEmpty()) {
+ return new MatchNoneQueryBuilder();
+ }
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null && context.fieldMapper(IdFieldMapper.NAME) == null) {
+ // no mappings yet
+ return new MatchNoneQueryBuilder();
+ }
+ return super.doRewrite(queryRewriteContext);
+ }
+
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
MappedFieldType idField = context.fieldMapper(IdFieldMapper.NAME);
- if (idField == null) {
- return new MatchNoDocsQuery("No mappings");
- }
- if (this.ids.isEmpty()) {
- return Queries.newMatchNoDocsQuery("Missing ids in \"" + this.getName() + "\" query.");
- } else {
- return idField.termsQuery(new ArrayList<>(ids), context);
+ if (idField == null || ids.isEmpty()) {
+ throw new IllegalStateException("Rewrite first");
}
+ return idField.termsQuery(new ArrayList<>(ids), context);
}
@Override
diff --git a/server/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java
index db596e2ecfc7b..44c8dd44b49c8 100644
--- a/server/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java
@@ -19,20 +19,20 @@
package org.elasticsearch.index.query;
-import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.MultiTermQuery;
-import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.mapper.ConstantFieldType;
import org.elasticsearch.index.query.support.QueryParsers;
import java.io.IOException;
@@ -171,14 +171,26 @@ public String getWriteableName() {
@Override
protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
- if ("_index".equals(fieldName)) {
- // Special-case optimisation for canMatch phase:
- // We can skip querying this shard if the index name doesn't match the value of this query on the "_index" field.
- QueryShardContext shardContext = queryRewriteContext.convertToShardContext();
- if (shardContext != null && shardContext.indexMatches(value + "*") == false) {
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null) {
+ MappedFieldType fieldType = context.fieldMapper(this.fieldName);
+ if (fieldType == null) {
return new MatchNoneQueryBuilder();
- }
+ } else if (fieldType instanceof ConstantFieldType) {
+ // This logic is correct for all field types, but by only applying it to constant
+ // fields we also have the guarantee that it doesn't perform I/O, which is important
+ // since rewrites might happen on a network thread.
+ Query query = fieldType.prefixQuery(value, null, context); // the rewrite method doesn't matter
+ if (query instanceof MatchAllDocsQuery) {
+ return new MatchAllQueryBuilder();
+ } else if (query instanceof MatchNoDocsQuery) {
+ return new MatchNoneQueryBuilder();
+ } else {
+ assert false : "Constant fields must produce match-all or match-none queries, got " + query ;
+ }
+ }
}
+
return super.doRewrite(queryRewriteContext);
}
@@ -186,20 +198,11 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws
protected Query doToQuery(QueryShardContext context) throws IOException {
MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(rewrite, null, LoggingDeprecationHandler.INSTANCE);
- Query query = null;
MappedFieldType fieldType = context.fieldMapper(fieldName);
- if (fieldType != null) {
- query = fieldType.prefixQuery(value, method, context);
+ if (fieldType == null) {
+ throw new IllegalStateException("Rewrite first");
}
- if (query == null) {
- PrefixQuery prefixQuery = new PrefixQuery(new Term(fieldName, BytesRefs.toBytesRef(value)));
- if (method != null) {
- prefixQuery.setRewriteMethod(method);
- }
- query = prefixQuery;
- }
-
- return query;
+ return fieldType.prefixQuery(value, method, context);
}
@Override
diff --git a/server/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java
index 156fa27264e1f..6cb1704611ba0 100644
--- a/server/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java
@@ -21,7 +21,6 @@
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
@@ -29,14 +28,12 @@
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.common.time.DateMathParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
-import org.elasticsearch.index.mapper.MapperService;
import java.io.IOException;
import java.time.DateTimeException;
@@ -432,21 +429,23 @@ public String getWriteableName() {
// Overridable for testing only
protected MappedFieldType.Relation getRelation(QueryRewriteContext queryRewriteContext) throws IOException {
QueryShardContext shardContext = queryRewriteContext.convertToShardContext();
- // If the context is null we are not on the shard and cannot
- // rewrite so just pretend there is an intersection so that the rewrite is a noop
- if (shardContext == null || shardContext.getIndexReader() == null) {
- return MappedFieldType.Relation.INTERSECTS;
- }
- final MapperService mapperService = shardContext.getMapperService();
- final MappedFieldType fieldType = mapperService.fieldType(fieldName);
- if (fieldType == null) {
- // no field means we have no values
- return MappedFieldType.Relation.DISJOINT;
- } else {
+ if (shardContext != null) {
+ final MappedFieldType fieldType = shardContext.fieldMapper(fieldName);
+ if (fieldType == null) {
+ return MappedFieldType.Relation.DISJOINT;
+ }
+ if (shardContext.getIndexReader() == null) {
+ // No reader, this may happen e.g. for percolator queries.
+ return MappedFieldType.Relation.INTERSECTS;
+ }
+
DateMathParser dateMathParser = getForceDateParser();
return fieldType.isFieldWithinQuery(shardContext.getIndexReader(), from, to, includeLower,
includeUpper, timeZone, dateMathParser, queryRewriteContext);
}
+
+ // Not on the shard, we have no way to know what the relation is.
+ return MappedFieldType.Relation.INTERSECTS;
}
@Override
@@ -490,26 +489,14 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
return ExistsQueryBuilder.newFilter(context, fieldName);
}
}
- Query query = null;
MappedFieldType mapper = context.fieldMapper(this.fieldName);
- if (mapper != null) {
- DateMathParser forcedDateParser = getForceDateParser();
- query = mapper.rangeQuery(
- from, to, includeLower, includeUpper,
- relation, timeZone, forcedDateParser, context);
- } else {
- if (timeZone != null) {
- throw new QueryShardException(context, "[range] time_zone can not be applied to non unmapped field ["
- + fieldName + "]");
- }
- }
-
- if (query == null) {
- query = new TermRangeQuery(this.fieldName,
- BytesRefs.toBytesRef(from), BytesRefs.toBytesRef(to),
- includeLower, includeUpper);
+ if (mapper == null) {
+ throw new IllegalStateException("Rewrite first");
}
- return query;
+ DateMathParser forcedDateParser = getForceDateParser();
+ return mapper.rangeQuery(
+ from, to, includeLower, includeUpper,
+ relation, timeZone, forcedDateParser, context);
}
@Override
diff --git a/server/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java
index 49e5e53e1ed91..d55f9bceaa9bd 100644
--- a/server/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilder.java
@@ -126,11 +126,16 @@ public static SpanMultiTermQueryBuilder fromXContent(XContentParser parser) thro
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
- if (multiTermQueryBuilder instanceof PrefixQueryBuilder) {
+ // We do the rewrite in toQuery to not have to deal with the case when a multi-term builder rewrites to a non-multi-term
+ // builder.
+ QueryBuilder multiTermQueryBuilder = Rewriteable.rewrite(this.multiTermQueryBuilder, context);
+ if (multiTermQueryBuilder instanceof MatchNoneQueryBuilder) {
+ return new SpanMatchNoDocsQuery(this.multiTermQueryBuilder.fieldName(), "Inner query rewrote to match_none");
+ } else if (multiTermQueryBuilder instanceof PrefixQueryBuilder) {
PrefixQueryBuilder prefixBuilder = (PrefixQueryBuilder) multiTermQueryBuilder;
- MappedFieldType fieldType = context.fieldMapper(multiTermQueryBuilder.fieldName());
+ MappedFieldType fieldType = context.fieldMapper(prefixBuilder.fieldName());
if (fieldType == null) {
- return new SpanMatchNoDocsQuery(multiTermQueryBuilder.fieldName(), "unknown field");
+ throw new IllegalStateException("Rewrite first");
}
final SpanMultiTermQueryWrapper.SpanRewriteMethod spanRewriteMethod;
if (prefixBuilder.rewrite() != null) {
@@ -159,7 +164,7 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
}
}
if (subQuery instanceof MatchNoDocsQuery) {
- return new SpanMatchNoDocsQuery(multiTermQueryBuilder.fieldName(), subQuery.toString());
+ return new SpanMatchNoDocsQuery(this.multiTermQueryBuilder.fieldName(), subQuery.toString());
} else if (subQuery instanceof MultiTermQuery == false) {
throw new UnsupportedOperationException("unsupported inner query, should be "
+ MultiTermQuery.class.getName() + " but was " + subQuery.getClass().getName());
diff --git a/server/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java
index 262bfb2c6b5b3..8a0118d26e8db 100644
--- a/server/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/TermQueryBuilder.java
@@ -19,15 +19,15 @@
package org.elasticsearch.index.query;
-import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.mapper.ConstantFieldType;
import java.io.IOException;
@@ -132,28 +132,35 @@ public static TermQueryBuilder fromXContent(XContentParser parser) throws IOExce
@Override
protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
- if ("_index".equals(fieldName)) {
- // Special-case optimisation for canMatch phase:
- // We can skip querying this shard if the index name doesn't match the value of this query on the "_index" field.
- QueryShardContext shardContext = queryRewriteContext.convertToShardContext();
- if (shardContext != null && shardContext.indexMatches(BytesRefs.toString(value)) == false) {
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null) {
+ MappedFieldType fieldType = context.fieldMapper(this.fieldName);
+ if (fieldType == null) {
return new MatchNoneQueryBuilder();
- }
+ } else if (fieldType instanceof ConstantFieldType) {
+ // This logic is correct for all field types, but by only applying it to constant
+ // fields we also have the guarantee that it doesn't perform I/O, which is important
+ // since rewrites might happen on a network thread.
+ Query query = fieldType.termQuery(value, context);
+ if (query instanceof MatchAllDocsQuery) {
+ return new MatchAllQueryBuilder();
+ } else if (query instanceof MatchNoDocsQuery) {
+ return new MatchNoneQueryBuilder();
+ } else {
+ assert false : "Constant fields must produce match-all or match-none queries, got " + query ;
+ }
+ }
}
return super.doRewrite(queryRewriteContext);
}
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
- Query query = null;
MappedFieldType mapper = context.fieldMapper(this.fieldName);
- if (mapper != null) {
- query = mapper.termQuery(this.value, context);
- }
- if (query == null) {
- query = new TermQuery(new Term(this.fieldName, BytesRefs.toBytesRef(this.value)));
+ if (mapper == null) {
+ throw new IllegalStateException("Rewrite first");
}
- return query;
+ return mapper.termQuery(this.value, context);
}
@Override
diff --git a/server/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java
index 2cececd041b18..a7a5dfc42c8cb 100644
--- a/server/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java
@@ -19,8 +19,9 @@
package org.elasticsearch.index.query;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
-import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.apache.lucene.util.SetOnce;
@@ -33,13 +34,12 @@
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.BytesRefs;
-import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.mapper.ConstantFieldType;
import org.elasticsearch.indices.TermsLookup;
import java.io.IOException;
@@ -417,12 +417,9 @@ public String getWriteableName() {
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
- if (termsLookup != null || supplier != null) {
+ if (termsLookup != null || supplier != null || values == null || values.isEmpty()) {
throw new UnsupportedOperationException("query must be rewritten first");
}
- if (values == null || values.isEmpty()) {
- return Queries.newMatchNoDocsQuery("No terms supplied for \"" + getName() + "\" query.");
- }
int maxTermsCount = context.getIndexSettings().getMaxTermsCount();
if (values.size() > maxTermsCount){
throw new IllegalArgumentException(
@@ -431,16 +428,10 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
IndexSettings.MAX_TERMS_COUNT_SETTING.getKey() + "] index level setting.");
}
MappedFieldType fieldType = context.fieldMapper(fieldName);
-
- if (fieldType != null) {
- return fieldType.termsQuery(values, context);
- } else {
- BytesRef[] filterValues = new BytesRef[values.size()];
- for (int i = 0; i < filterValues.length; i++) {
- filterValues[i] = BytesRefs.toBytesRef(values.get(i));
- }
- return new TermInSetQuery(fieldName, filterValues);
+ if (fieldType == null) {
+ throw new IllegalStateException("Rewrite first");
}
+ return fieldType.termsQuery(values, context);
}
private void fetch(TermsLookup termsLookup, Client client, ActionListener> actionListener) {
@@ -482,21 +473,31 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) {
})));
return new TermsQueryBuilder(this.fieldName, supplier::get);
}
- if ("_index".equals(this.fieldName) && values != null) {
- // Special-case optimisation for canMatch phase:
- // We can skip querying this shard if the index name doesn't match any of the search terms.
- QueryShardContext shardContext = queryRewriteContext.convertToShardContext();
- if (shardContext != null) {
- for (Object localValue : values) {
- if (shardContext.indexMatches(BytesRefs.toString(localValue))) {
- // We can match - at least one index name matches
- return this;
- }
- }
- // all index names are invalid - no possibility of a match on this shard.
+
+ if (values == null || values.isEmpty()) {
+ return new MatchNoneQueryBuilder();
+ }
+
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null) {
+ MappedFieldType fieldType = context.fieldMapper(this.fieldName);
+ if (fieldType == null) {
return new MatchNoneQueryBuilder();
+ } else if (fieldType instanceof ConstantFieldType) {
+ // This logic is correct for all field types, but by only applying it to constant
+ // fields we also have the guarantee that it doesn't perform I/O, which is important
+ // since rewrites might happen on a network thread.
+ Query query = fieldType.termsQuery(values, context);
+ if (query instanceof MatchAllDocsQuery) {
+ return new MatchAllQueryBuilder();
+ } else if (query instanceof MatchNoDocsQuery) {
+ return new MatchNoneQueryBuilder();
+ } else {
+ assert false : "Constant fields must produce match-all or match-none queries, got " + query ;
+ }
}
}
+
return this;
}
}
diff --git a/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
index 115fa8d476dfd..39ca3b0a45b6f 100644
--- a/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
+++ b/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java
@@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
+import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
@@ -27,11 +28,11 @@
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.MappedFieldType;
+import org.elasticsearch.index.mapper.ConstantFieldType;
import org.elasticsearch.index.query.support.QueryParsers;
import java.io.IOException;
@@ -182,14 +183,26 @@ public static WildcardQueryBuilder fromXContent(XContentParser parser) throws IO
@Override
protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) throws IOException {
- if ("_index".equals(fieldName)) {
- // Special-case optimisation for canMatch phase:
- // We can skip querying this shard if the index name doesn't match the value of this query on the "_index" field.
- QueryShardContext shardContext = queryRewriteContext.convertToShardContext();
- if (shardContext != null && shardContext.indexMatches(BytesRefs.toString(value)) == false) {
+ QueryShardContext context = queryRewriteContext.convertToShardContext();
+ if (context != null) {
+ MappedFieldType fieldType = context.fieldMapper(this.fieldName);
+ if (fieldType == null) {
return new MatchNoneQueryBuilder();
- }
+ } else if (fieldType instanceof ConstantFieldType) {
+ // This logic is correct for all field types, but by only applying it to constant
+ // fields we also have the guarantee that it doesn't perform I/O, which is important
+ // since rewrites might happen on a network thread.
+ Query query = fieldType.wildcardQuery(value, null, context); // the rewrite method doesn't matter
+ if (query instanceof MatchAllDocsQuery) {
+ return new MatchAllQueryBuilder();
+ } else if (query instanceof MatchNoDocsQuery) {
+ return new MatchNoneQueryBuilder();
+ } else {
+ assert false : "Constant fields must produce match-all or match-none queries, got " + query ;
+ }
+ }
}
+
return super.doRewrite(queryRewriteContext);
}
@@ -198,7 +211,7 @@ protected Query doToQuery(QueryShardContext context) throws IOException {
MappedFieldType fieldType = context.fieldMapper(fieldName);
if (fieldType == null) {
- return new MatchNoDocsQuery("unknown field [" + fieldName + "]");
+ throw new IllegalStateException("Rewrite first");
}
MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(
diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/SignificantTermsAggregationBuilder.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/SignificantTermsAggregationBuilder.java
index 81d1b0445b3e2..45a755d07b286 100644
--- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/SignificantTermsAggregationBuilder.java
+++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/significant/SignificantTermsAggregationBuilder.java
@@ -26,6 +26,7 @@
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryBuilder;
+import org.elasticsearch.index.query.QueryRewriteContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
@@ -127,10 +128,23 @@ protected SignificantTermsAggregationBuilder(SignificantTermsAggregationBuilder
}
@Override
- protected AggregationBuilder shallowCopy(Builder factoriesBuilder, Map metaData) {
+ protected SignificantTermsAggregationBuilder shallowCopy(Builder factoriesBuilder, Map metaData) {
return new SignificantTermsAggregationBuilder(this, factoriesBuilder, metaData);
}
+ @Override
+ protected AggregationBuilder doRewrite(QueryRewriteContext queryShardContext) throws IOException {
+ if (filterBuilder != null) {
+ QueryBuilder rewrittenFilter = filterBuilder.rewrite(queryShardContext);
+ if (rewrittenFilter != filterBuilder) {
+ SignificantTermsAggregationBuilder rewritten = shallowCopy(factoriesBuilder, metaData);
+ rewritten.backgroundFilter(rewrittenFilter);
+ return rewritten;
+ }
+ }
+ return super.doRewrite(queryShardContext);
+ }
+
@Override
protected void innerWriteTo(StreamOutput out) throws IOException {
bucketCountThresholds.writeTo(out);
diff --git a/server/src/test/java/org/elasticsearch/index/query/BoolQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/BoolQueryBuilderTests.java
index 70826f7aab1e8..3e859035b51b2 100644
--- a/server/src/test/java/org/elasticsearch/index/query/BoolQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/BoolQueryBuilderTests.java
@@ -22,6 +22,7 @@
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -85,7 +86,7 @@ protected void doAssertLuceneQuery(BoolQueryBuilder queryBuilder, Query query, Q
if (clauses.isEmpty()) {
assertThat(query, instanceOf(MatchAllDocsQuery.class));
- } else {
+ } else if (query instanceof MatchNoDocsQuery == false) {
assertThat(query, instanceOf(BooleanQuery.class));
BooleanQuery booleanQuery = (BooleanQuery) query;
if (queryBuilder.adjustPureNegative()) {
@@ -113,7 +114,7 @@ private static List getBooleanClauses(List queryBui
BooleanClause.Occur occur, QueryShardContext context) throws IOException {
List clauses = new ArrayList<>();
for (QueryBuilder query : queryBuilders) {
- Query innerQuery = query.toQuery(context);
+ Query innerQuery = query.rewrite(context).toQuery(context);
if (innerQuery != null) {
clauses.add(new BooleanClause(innerQuery, occur));
}
@@ -195,15 +196,15 @@ public void testMinShouldMatchFilterWithoutShouldClauses() throws Exception {
public void testMinShouldMatchBiggerThanNumberOfShouldClauses() throws Exception {
BooleanQuery bq = (BooleanQuery) parseQuery(
boolQuery()
- .should(termQuery("foo", "bar"))
- .should(termQuery("foo2", "bar2"))
+ .should(termQuery(STRING_FIELD_NAME, "bar"))
+ .should(termQuery(STRING_FIELD_NAME_2, "bar2"))
.minimumShouldMatch("3")).toQuery(createShardContext());
assertEquals(3, bq.getMinimumNumberShouldMatch());
bq = (BooleanQuery) parseQuery(
boolQuery()
- .should(termQuery("foo", "bar"))
- .should(termQuery("foo2", "bar2"))
+ .should(termQuery(STRING_FIELD_NAME, "bar"))
+ .should(termQuery(STRING_FIELD_NAME_2, "bar2"))
.minimumShouldMatch(3)).toQuery(createShardContext());
assertEquals(3, bq.getMinimumNumberShouldMatch());
}
@@ -211,8 +212,8 @@ public void testMinShouldMatchBiggerThanNumberOfShouldClauses() throws Exception
public void testMinShouldMatchDisableCoord() throws Exception {
BooleanQuery bq = (BooleanQuery) parseQuery(
boolQuery()
- .should(termQuery("foo", "bar"))
- .should(termQuery("foo2", "bar2"))
+ .should(termQuery(STRING_FIELD_NAME, "bar"))
+ .should(termQuery(STRING_FIELD_NAME, "bar2"))
.minimumShouldMatch("3")).toQuery(createShardContext());
assertEquals(3, bq.getMinimumNumberShouldMatch());
}
@@ -291,22 +292,22 @@ public void testRewrite() throws IOException {
boolean mustRewrite = false;
if (randomBoolean()) {
mustRewrite = true;
- boolQueryBuilder.must(new WrapperQueryBuilder(new TermsQueryBuilder("foo", "must").toString()));
+ boolQueryBuilder.must(new WrapperQueryBuilder(new TermsQueryBuilder(STRING_FIELD_NAME, "must").toString()));
}
if (randomBoolean()) {
mustRewrite = true;
- boolQueryBuilder.should(new WrapperQueryBuilder(new TermsQueryBuilder("foo", "should").toString()));
+ boolQueryBuilder.should(new WrapperQueryBuilder(new TermsQueryBuilder(STRING_FIELD_NAME, "should").toString()));
}
if (randomBoolean()) {
mustRewrite = true;
- boolQueryBuilder.filter(new WrapperQueryBuilder(new TermsQueryBuilder("foo", "filter").toString()));
+ boolQueryBuilder.filter(new WrapperQueryBuilder(new TermsQueryBuilder(STRING_FIELD_NAME, "filter").toString()));
}
if (randomBoolean()) {
mustRewrite = true;
- boolQueryBuilder.mustNot(new WrapperQueryBuilder(new TermsQueryBuilder("foo", "must_not").toString()));
+ boolQueryBuilder.mustNot(new WrapperQueryBuilder(new TermsQueryBuilder(STRING_FIELD_NAME, "must_not").toString()));
}
if (mustRewrite == false && randomBoolean()) {
- boolQueryBuilder.must(new TermsQueryBuilder("foo", "no_rewrite"));
+ boolQueryBuilder.must(new TermsQueryBuilder(STRING_FIELD_NAME, "no_rewrite"));
}
QueryBuilder rewritten = boolQueryBuilder.rewrite(createShardContext());
if (mustRewrite == false && boolQueryBuilder.must().isEmpty()) {
@@ -317,16 +318,16 @@ public void testRewrite() throws IOException {
if (mustRewrite) {
assertNotSame(rewrite, boolQueryBuilder);
if (boolQueryBuilder.must().isEmpty() == false) {
- assertEquals(new TermsQueryBuilder("foo", "must"), rewrite.must().get(0));
+ assertEquals(new TermsQueryBuilder(STRING_FIELD_NAME, "must"), rewrite.must().get(0));
}
if (boolQueryBuilder.should().isEmpty() == false) {
- assertEquals(new TermsQueryBuilder("foo", "should"), rewrite.should().get(0));
+ assertEquals(new TermsQueryBuilder(STRING_FIELD_NAME, "should"), rewrite.should().get(0));
}
if (boolQueryBuilder.mustNot().isEmpty() == false) {
- assertEquals(new TermsQueryBuilder("foo", "must_not"), rewrite.mustNot().get(0));
+ assertEquals(new TermsQueryBuilder(STRING_FIELD_NAME, "must_not"), rewrite.mustNot().get(0));
}
if (boolQueryBuilder.filter().isEmpty() == false) {
- assertEquals(new TermsQueryBuilder("foo", "filter"), rewrite.filter().get(0));
+ assertEquals(new TermsQueryBuilder(STRING_FIELD_NAME, "filter"), rewrite.filter().get(0));
}
} else {
assertSame(rewrite, boolQueryBuilder);
@@ -359,14 +360,14 @@ public void testRewriteWithMatchNone() throws IOException {
assertEquals(new MatchNoneQueryBuilder(), rewritten);
boolQueryBuilder = new BoolQueryBuilder();
- boolQueryBuilder.must(new TermQueryBuilder("foo","bar"));
+ boolQueryBuilder.must(new TermQueryBuilder(STRING_FIELD_NAME,"bar"));
boolQueryBuilder.filter(new WrapperQueryBuilder(new WrapperQueryBuilder(new MatchNoneQueryBuilder().toString()).toString()));
rewritten = boolQueryBuilder.rewrite(createShardContext());
assertEquals(new MatchNoneQueryBuilder(), rewritten);
boolQueryBuilder = new BoolQueryBuilder();
- boolQueryBuilder.must(new TermQueryBuilder("foo","bar"));
- boolQueryBuilder.filter(new BoolQueryBuilder().should(new TermQueryBuilder("foo","bar"))
+ boolQueryBuilder.must(new TermQueryBuilder(STRING_FIELD_NAME,"bar"));
+ boolQueryBuilder.filter(new BoolQueryBuilder().should(new TermQueryBuilder(STRING_FIELD_NAME,"bar"))
.filter(new MatchNoneQueryBuilder()));
rewritten = Rewriteable.rewrite(boolQueryBuilder, createShardContext());
assertEquals(new MatchNoneQueryBuilder(), rewritten);
@@ -377,7 +378,7 @@ public void testRewriteWithMatchNone() throws IOException {
assertEquals(new MatchNoneQueryBuilder(), rewritten);
boolQueryBuilder = new BoolQueryBuilder();
- boolQueryBuilder.should(new TermQueryBuilder("foo", "bar"));
+ boolQueryBuilder.should(new TermQueryBuilder(STRING_FIELD_NAME, "bar"));
boolQueryBuilder.should(new WrapperQueryBuilder(new MatchNoneQueryBuilder().toString()));
rewritten = Rewriteable.rewrite(boolQueryBuilder, createShardContext());
assertNotEquals(new MatchNoneQueryBuilder(), rewritten);
@@ -386,4 +387,16 @@ public void testRewriteWithMatchNone() throws IOException {
rewritten = Rewriteable.rewrite(boolQueryBuilder, createShardContext());
assertNotEquals(new MatchNoneQueryBuilder(), rewritten);
}
+
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ TermQueryBuilder termQuery = new TermQueryBuilder("unmapped_field", 42);
+ BoolQueryBuilder boolQuery = new BoolQueryBuilder();
+ boolQuery.must(termQuery);
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> boolQuery.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/BoostingQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/BoostingQueryBuilderTests.java
index 534126ee5f35a..22d4db861be82 100644
--- a/server/src/test/java/org/elasticsearch/index/query/BoostingQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/BoostingQueryBuilderTests.java
@@ -40,8 +40,8 @@ protected BoostingQueryBuilder doCreateTestQueryBuilder() {
@Override
protected void doAssertLuceneQuery(BoostingQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
- Query positive = queryBuilder.positiveQuery().toQuery(context);
- Query negative = queryBuilder.negativeQuery().toQuery(context);
+ Query positive = queryBuilder.positiveQuery().rewrite(context).toQuery(context);
+ Query negative = queryBuilder.negativeQuery().rewrite(context).toQuery(context);
if (positive == null || negative == null) {
assertThat(query, nullValue());
} else {
@@ -103,4 +103,22 @@ public void testRewrite() throws IOException {
assertEquals(new BoostingQueryBuilder(positive.rewrite(createShardContext()), negative.rewrite(createShardContext())), rewrite);
}
}
+
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+
+ BoostingQueryBuilder queryBuilder1 = new BoostingQueryBuilder(
+ new TermQueryBuilder("unmapped_field", "foo"), new MatchNoneQueryBuilder());
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder1.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+
+ BoostingQueryBuilder queryBuilder2 = new BoostingQueryBuilder(
+ new MatchAllQueryBuilder(), new TermQueryBuilder("unmapped_field", "foo"));
+ e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder2.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/ConstantScoreQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/ConstantScoreQueryBuilderTests.java
index fd2ad04af5f95..5281788a8307d 100644
--- a/server/src/test/java/org/elasticsearch/index/query/ConstantScoreQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/ConstantScoreQueryBuilderTests.java
@@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.ConstantScoreQuery;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.test.AbstractQueryTestCase;
@@ -41,9 +42,11 @@ protected ConstantScoreQueryBuilder doCreateTestQueryBuilder() {
@Override
protected void doAssertLuceneQuery(ConstantScoreQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
- Query innerQuery = queryBuilder.innerQuery().toQuery(context);
+ Query innerQuery = queryBuilder.innerQuery().rewrite(context).toQuery(context);
if (innerQuery == null) {
assertThat(query, nullValue());
+ } else if (innerQuery instanceof MatchNoDocsQuery) {
+ assertThat(query, instanceOf(MatchNoDocsQuery.class));
} else {
assertThat(query, instanceOf(ConstantScoreQuery.class));
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) query;
@@ -107,4 +110,14 @@ public void testRewriteToMatchNone() throws IOException {
QueryBuilder rewrite = constantScoreQueryBuilder.rewrite(createShardContext());
assertEquals(rewrite, new MatchNoneQueryBuilder());
}
+
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ ConstantScoreQueryBuilder queryBuilder = new ConstantScoreQueryBuilder(new TermQueryBuilder("unmapped_field", "foo"));
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java
index 06f197f4c137e..7185210caadb8 100644
--- a/server/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/IdsQueryBuilderTests.java
@@ -99,4 +99,14 @@ protected QueryBuilder parseQuery(XContentParser parser) throws IOException {
assertThat(query, instanceOf(IdsQueryBuilder.class));
return (IdsQueryBuilder) query;
}
+
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContextWithNoType();
+ context.setAllowUnmappedFields(true);
+ IdsQueryBuilder queryBuilder = createTestQueryBuilder();
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
index c7f703113f264..ab6601b507d1b 100644
--- a/server/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/NestedQueryBuilderTests.java
@@ -57,8 +57,6 @@
public class NestedQueryBuilderTests extends AbstractQueryTestCase {
- boolean requiresRewrite = false;
-
@Override
protected void initializeAdditionalMappings(MapperService mapperService) throws IOException {
mapperService.merge("_doc", new CompressedXContent(Strings.toString(PutMappingRequest.simpleMapping(
@@ -79,10 +77,6 @@ protected void initializeAdditionalMappings(MapperService mapperService) throws
@Override
protected NestedQueryBuilder doCreateTestQueryBuilder() {
QueryBuilder innerQueryBuilder = RandomQueryBuilder.createQuery(random());
- if (randomBoolean()) {
- requiresRewrite = true;
- innerQueryBuilder = new WrapperQueryBuilder(innerQueryBuilder.toString());
- }
NestedQueryBuilder nqb = new NestedQueryBuilder("nested1", innerQueryBuilder,
RandomPicks.randomFrom(random(), ScoreMode.values()));
nqb.ignoreUnmapped(randomBoolean());
@@ -185,13 +179,14 @@ public void testFromJson() throws IOException {
@Override
public void testMustRewrite() throws IOException {
- try {
- super.testMustRewrite();
- } catch (UnsupportedOperationException e) {
- if (requiresRewrite == false) {
- throw e;
- }
- }
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ TermQueryBuilder innerQueryBuilder = new TermQueryBuilder("nested1.unmapped_field", "foo");
+ NestedQueryBuilder nestedQueryBuilder = new NestedQueryBuilder("nested1", innerQueryBuilder,
+ RandomPicks.randomFrom(random(), ScoreMode.values()));
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> nestedQueryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
}
public void testIgnoreUnmapped() throws IOException {
diff --git a/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java
index dba92d712c107..94596ffd6c58d 100644
--- a/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/PrefixQueryBuilderTests.java
@@ -20,11 +20,13 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.test.AbstractQueryTestCase;
+import org.hamcrest.Matchers;
import java.io.IOException;
import java.util.HashMap;
@@ -68,12 +70,14 @@ private static PrefixQueryBuilder randomPrefixQuery() {
@Override
protected void doAssertLuceneQuery(PrefixQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
- assertThat(query, instanceOf(PrefixQuery.class));
- PrefixQuery prefixQuery = (PrefixQuery) query;
+ assertThat(query, Matchers.anyOf(instanceOf(PrefixQuery.class), instanceOf(MatchNoDocsQuery.class)));
+ if (context.fieldMapper(queryBuilder.fieldName()) != null) { // The field is mapped
+ PrefixQuery prefixQuery = (PrefixQuery) query;
- String expectedFieldName = expectedFieldName(queryBuilder.fieldName());
- assertThat(prefixQuery.getPrefix().field(), equalTo(expectedFieldName));
- assertThat(prefixQuery.getPrefix().text(), equalTo(queryBuilder.value()));
+ String expectedFieldName = expectedFieldName(queryBuilder.fieldName());
+ assertThat(prefixQuery.getPrefix().field(), equalTo(expectedFieldName));
+ assertThat(prefixQuery.getPrefix().text(), equalTo(queryBuilder.value()));
+ }
}
public void testIllegalArguments() {
@@ -88,10 +92,10 @@ public void testIllegalArguments() {
public void testBlendedRewriteMethod() throws IOException {
String rewrite = "top_terms_blended_freqs_10";
- Query parsedQuery = parseQuery(prefixQuery("field", "val").rewrite(rewrite)).toQuery(createShardContext());
+ Query parsedQuery = parseQuery(prefixQuery(STRING_FIELD_NAME, "val").rewrite(rewrite)).toQuery(createShardContext());
assertThat(parsedQuery, instanceOf(PrefixQuery.class));
PrefixQuery prefixQuery = (PrefixQuery) parsedQuery;
- assertThat(prefixQuery.getPrefix(), equalTo(new Term("field", "val")));
+ assertThat(prefixQuery.getPrefix(), equalTo(new Term(STRING_FIELD_NAME, "val")));
assertThat(prefixQuery.getRewriteMethod(), instanceOf(MultiTermQuery.TopTermsBlendedFreqScoringRewrite.class));
}
@@ -153,7 +157,16 @@ public void testRewriteIndexQueryToNotMatchNone() throws Exception {
PrefixQueryBuilder query = prefixQuery("_index", getIndex().getName());
QueryShardContext queryShardContext = createShardContext();
QueryBuilder rewritten = query.rewrite(queryShardContext);
- assertThat(rewritten, instanceOf(PrefixQueryBuilder.class));
+ assertThat(rewritten, instanceOf(MatchAllQueryBuilder.class));
}
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ PrefixQueryBuilder queryBuilder = new PrefixQueryBuilder("unmapped_field", "foo");
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java
index dfa19d1623d5d..c9c43a1e90186 100644
--- a/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/RangeQueryBuilderTests.java
@@ -52,7 +52,6 @@
import java.util.Map;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
-import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.sameInstance;
@@ -242,16 +241,6 @@ public void testIllegalArguments() {
expectThrows(IllegalArgumentException.class, () -> rangeQueryBuilder.format("badFormat"));
}
- /**
- * Specifying a timezone together with an unmapped field should throw an exception.
- */
- public void testToQueryUnmappedWithTimezone() throws QueryShardException {
- RangeQueryBuilder query = new RangeQueryBuilder("bogus_field");
- query.from(1).to(10).timeZone("UTC");
- QueryShardException e = expectThrows(QueryShardException.class, () -> query.toQuery(createShardContext()));
- assertThat(e.getMessage(), containsString("[range] time_zone can not be applied"));
- }
-
public void testToQueryNumericField() throws IOException {
Query parsedQuery = rangeQuery(INT_FIELD_NAME).from(23).to(54).includeLower(true).includeUpper(false).toQuery(createShardContext());
// since age is automatically registered in data, we encode it as numeric
diff --git a/server/src/test/java/org/elasticsearch/index/query/ScriptScoreQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/ScriptScoreQueryBuilderTests.java
index 04322a01d0f68..d3ff1434c4d2c 100644
--- a/server/src/test/java/org/elasticsearch/index/query/ScriptScoreQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/ScriptScoreQueryBuilderTests.java
@@ -99,6 +99,19 @@ public void testCacheability() throws IOException {
assertFalse("query should not be cacheable: " + queryBuilder.toString(), context.isCacheable());
}
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ TermQueryBuilder termQueryBuilder = new TermQueryBuilder("unmapped_field", "foo");
+ String scriptStr = "1";
+ Script script = new Script(ScriptType.INLINE, MockScriptEngine.NAME, scriptStr, Collections.emptyMap());
+ ScriptScoreQueryBuilder scriptScoreQueryBuilder = new ScriptScoreQueryBuilder(termQueryBuilder, script);
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> scriptScoreQueryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
+
public void testDisallowExpensiveQueries() {
QueryShardContext queryShardContext = mock(QueryShardContext.class);
when(queryShardContext.allowExpensiveQueries()).thenReturn(false);
diff --git a/server/src/test/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilderTests.java
index 52d2dfaad8634..232e9b20e25b9 100644
--- a/server/src/test/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/SpanMultiTermQueryBuilderTests.java
@@ -89,7 +89,8 @@ protected void doAssertLuceneQuery(SpanMultiTermQueryBuilder queryBuilder, Query
if (query instanceof SpanMatchNoDocsQuery) {
return;
}
- assertThat(query, either(instanceOf(SpanMultiTermQueryWrapper.class)).or(instanceOf(FieldMaskingSpanQuery.class)));
+ assertThat(query, either(instanceOf(SpanMultiTermQueryWrapper.class))
+ .or(instanceOf(FieldMaskingSpanQuery.class)));
if (query instanceof SpanMultiTermQueryWrapper) {
SpanMultiTermQueryWrapper wrapper = (SpanMultiTermQueryWrapper) query;
Query innerQuery = queryBuilder.innerQuery().toQuery(context);
diff --git a/server/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTests.java
index 0bf6ddbc57438..376aa54ef15b3 100644
--- a/server/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/TermQueryBuilderTests.java
@@ -21,11 +21,11 @@
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.index.Term;
+import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PointRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.common.ParsingException;
-import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.index.mapper.MappedFieldType;
import java.io.IOException;
@@ -91,7 +91,7 @@ protected TermQueryBuilder createQueryBuilder(String fieldName, Object value) {
@Override
protected void doAssertLuceneQuery(TermQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
- assertThat(query, either(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class)));
+ assertThat(query, either(instanceOf(TermQuery.class)).or(instanceOf(PointRangeQuery.class)).or(instanceOf(MatchNoDocsQuery.class)));
MappedFieldType mapper = context.fieldMapper(queryBuilder.fieldName());
if (query instanceof TermQuery) {
TermQuery termQuery = (TermQuery) query;
@@ -99,14 +99,12 @@ protected void doAssertLuceneQuery(TermQueryBuilder queryBuilder, Query query, Q
String expectedFieldName = expectedFieldName(queryBuilder.fieldName());
assertThat(termQuery.getTerm().field(), equalTo(expectedFieldName));
- if (mapper != null) {
- Term term = ((TermQuery) mapper.termQuery(queryBuilder.value(), null)).getTerm();
- assertThat(termQuery.getTerm(), equalTo(term));
- } else {
- assertThat(termQuery.getTerm().bytes(), equalTo(BytesRefs.toBytesRef(queryBuilder.value())));
- }
- } else {
+ Term term = ((TermQuery) mapper.termQuery(queryBuilder.value(), null)).getTerm();
+ assertThat(termQuery.getTerm(), equalTo(term));
+ } else if (mapper != null) {
assertEquals(query, mapper.termQuery(queryBuilder.value(), null));
+ } else {
+ assertThat(query, instanceOf(MatchNoDocsQuery.class));
}
}
@@ -185,6 +183,16 @@ public void testRewriteIndexQueryToNotMatchNone() throws IOException {
TermQueryBuilder query = QueryBuilders.termQuery("_index", getIndex().getName());
QueryShardContext queryShardContext = createShardContext();
QueryBuilder rewritten = query.rewrite(queryShardContext);
- assertThat(rewritten, instanceOf(TermQueryBuilder.class));
- }
+ assertThat(rewritten, instanceOf(MatchAllQueryBuilder.class));
+ }
+
+ @Override
+ public void testMustRewrite() throws IOException {
+ QueryShardContext context = createShardContext();
+ context.setAllowUnmappedFields(true);
+ TermQueryBuilder queryBuilder = new TermQueryBuilder("unmapped_field", "foo");
+ IllegalStateException e = expectThrows(IllegalStateException.class,
+ () -> queryBuilder.toQuery(context));
+ assertEquals("Rewrite first", e.getMessage());
+ }
}
diff --git a/server/src/test/java/org/elasticsearch/index/query/TermsQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/TermsQueryBuilderTests.java
index b4a42e65e5f8a..c772c4d431670 100644
--- a/server/src/test/java/org/elasticsearch/index/query/TermsQueryBuilderTests.java
+++ b/server/src/test/java/org/elasticsearch/index/query/TermsQueryBuilderTests.java
@@ -108,16 +108,13 @@ private TermsLookup randomTermsLookup() {
protected void doAssertLuceneQuery(TermsQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
if (queryBuilder.termsLookup() == null && (queryBuilder.values() == null || queryBuilder.values().isEmpty())) {
assertThat(query, instanceOf(MatchNoDocsQuery.class));
- MatchNoDocsQuery matchNoDocsQuery = (MatchNoDocsQuery) query;
- assertThat(matchNoDocsQuery.toString(), containsString("No terms supplied for \"terms\" query."));
} else if (queryBuilder.termsLookup() != null && randomTerms.size() == 0){
assertThat(query, instanceOf(MatchNoDocsQuery.class));
- MatchNoDocsQuery matchNoDocsQuery = (MatchNoDocsQuery) query;
- assertThat(matchNoDocsQuery.toString(), containsString("No terms supplied for \"terms\" query."));
} else {
assertThat(query, either(instanceOf(TermInSetQuery.class))
.or(instanceOf(PointInSetQuery.class))
- .or(instanceOf(ConstantScoreQuery.class)));
+ .or(instanceOf(ConstantScoreQuery.class))
+ .or(instanceOf(MatchNoDocsQuery.class)));
if (query instanceof ConstantScoreQuery) {
assertThat(((ConstantScoreQuery) query).getQuery(), instanceOf(BooleanQuery.class));
}
@@ -137,8 +134,13 @@ protected void doAssertLuceneQuery(TermsQueryBuilder queryBuilder, Query query,
}
String fieldName = expectedFieldName(queryBuilder.fieldName());
- TermInSetQuery expected = new TermInSetQuery(fieldName,
- terms.stream().filter(Objects::nonNull).map(Object::toString).map(BytesRef::new).collect(Collectors.toList()));
+ Query expected;
+ if (context.fieldMapper(fieldName) != null) {
+ expected = new TermInSetQuery(fieldName,
+ terms.stream().filter(Objects::nonNull).map(Object::toString).map(BytesRef::new).collect(Collectors.toList()));
+ } else {
+ expected = new MatchNoDocsQuery();
+ }
assertEquals(expected, query);
}
}
@@ -263,8 +265,16 @@ public void testMustRewrite() throws IOException {
UnsupportedOperationException e = expectThrows(UnsupportedOperationException.class,
() -> termsQueryBuilder.toQuery(createShardContext()));
assertEquals("query must be rewritten first", e.getMessage());
- assertEquals(rewriteAndFetch(termsQueryBuilder, createShardContext()), new TermsQueryBuilder(STRING_FIELD_NAME,
- randomTerms.stream().filter(x -> x != null).collect(Collectors.toList()))); // terms lookup removes null values
+
+ // terms lookup removes null values
+ List