From f5e406484d447cf143ee9097d1b2a82d514124bb Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Wed, 26 Sep 2018 10:46:53 -0700 Subject: [PATCH] When creating wildcard queries, use MatchNoDocsQuery when the field type doesn't exist. --- .../ICUCollationKeywordFieldMapper.java | 5 ++- .../index/mapper/CollationFieldTypeTests.java | 2 +- .../index/mapper/IndexFieldMapper.java | 5 ++- .../index/mapper/MappedFieldType.java | 4 ++- .../index/mapper/StringFieldType.java | 16 ++++++---- .../index/query/WildcardQueryBuilder.java | 19 +++--------- .../query/WildcardQueryBuilderTests.java | 31 ++++++++----------- 7 files changed, 40 insertions(+), 42 deletions(-) diff --git a/plugins/analysis-icu/src/main/java/org/elasticsearch/index/mapper/ICUCollationKeywordFieldMapper.java b/plugins/analysis-icu/src/main/java/org/elasticsearch/index/mapper/ICUCollationKeywordFieldMapper.java index c44152dd5013c..2c20d4b47844e 100644 --- a/plugins/analysis-icu/src/main/java/org/elasticsearch/index/mapper/ICUCollationKeywordFieldMapper.java +++ b/plugins/analysis-icu/src/main/java/org/elasticsearch/index/mapper/ICUCollationKeywordFieldMapper.java @@ -33,6 +33,7 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.common.settings.Settings; @@ -167,7 +168,9 @@ public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, Quer } @Override - public Query wildcardQuery(String value, QueryShardContext context) { + public Query wildcardQuery(String value, + @Nullable MultiTermQuery.RewriteMethod method, + QueryShardContext context) { throw new UnsupportedOperationException("[wildcard] queries are not supported on [" + CONTENT_TYPE + "] fields."); } diff --git a/plugins/analysis-icu/src/test/java/org/elasticsearch/index/mapper/CollationFieldTypeTests.java b/plugins/analysis-icu/src/test/java/org/elasticsearch/index/mapper/CollationFieldTypeTests.java index f90971412358d..a261e8b3b7e9a 100644 --- a/plugins/analysis-icu/src/test/java/org/elasticsearch/index/mapper/CollationFieldTypeTests.java +++ b/plugins/analysis-icu/src/test/java/org/elasticsearch/index/mapper/CollationFieldTypeTests.java @@ -126,7 +126,7 @@ public void testWildcardQuery() { ft.setName("field"); ft.setIndexOptions(IndexOptions.DOCS); expectThrows(UnsupportedOperationException.class, - () -> ft.wildcardQuery("foo*", null)); + () -> ft.wildcardQuery("foo*", null, null)); } public void testRangeQuery() { 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 fac00907980fd..456805e64160e 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java @@ -22,6 +22,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; @@ -151,7 +152,9 @@ public Query termsQuery(List values, QueryShardContext context) { } @Override - public Query wildcardQuery(String value, QueryShardContext context) { + public Query wildcardQuery(String value, + @Nullable MultiTermQuery.RewriteMethod method, + QueryShardContext context) { if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) { return Queries.newMatchAllQuery(); } else { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 5a2c8991e0aaa..45bb5ed395dc0 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -345,7 +345,9 @@ public Query prefixQuery(String value, @Nullable MultiTermQuery.RewriteMethod me throw new QueryShardException(context, "Can only use prefix queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); } - public Query wildcardQuery(String value, QueryShardContext context) { + public Query wildcardQuery(String value, + @Nullable MultiTermQuery.RewriteMethod method, + QueryShardContext context) { throw new QueryShardException(context, "Can only use wildcard queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java b/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java index 857c588717b2a..cde8e392dabb8 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java @@ -19,23 +19,24 @@ package org.elasticsearch.index.mapper; -import java.util.List; - import org.apache.lucene.index.Term; +import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.MatchNoDocsQuery; -import org.apache.lucene.search.TermInSetQuery; -import org.apache.lucene.search.FuzzyQuery; import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.RegexpQuery; +import org.apache.lucene.search.TermInSetQuery; import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.index.query.support.QueryParsers; + +import java.util.List; /** Base class for {@link MappedFieldType} implementations that use the same * representation for internal index terms as the external representation so @@ -78,13 +79,16 @@ public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, Quer } @Override - public Query wildcardQuery(String value, QueryShardContext context) { + public Query wildcardQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) { Query termQuery = termQuery(value, context); if (termQuery instanceof MatchNoDocsQuery || termQuery instanceof MatchAllDocsQuery) { return termQuery; } Term term = MappedFieldType.extractTerm(termQuery); - return new WildcardQuery(term); + + WildcardQuery query = new WildcardQuery(term); + QueryParsers.setRewriteMethod(query, method); + return query; } @Override 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 489286d309472..697e7ac864e85 100644 --- a/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java @@ -19,16 +19,14 @@ 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.Query; -import org.apache.lucene.search.WildcardQuery; 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; @@ -184,20 +182,13 @@ public static WildcardQueryBuilder fromXContent(XContentParser parser) throws IO protected Query doToQuery(QueryShardContext context) throws IOException { MappedFieldType fieldType = context.fieldMapper(fieldName); - Query query; if (fieldType == null) { - Term term = new Term(fieldName, BytesRefs.toBytesRef(value)); - query = new WildcardQuery(term); - } else { - query = fieldType.wildcardQuery(value, context); + return new MatchNoDocsQuery("unknown field [" + fieldName + "]"); } - if (query instanceof MultiTermQuery) { - MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod( - rewrite, null, LoggingDeprecationHandler.INSTANCE); - QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod); - } - return query; + MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod( + rewrite, null, LoggingDeprecationHandler.INSTANCE); + return fieldType.wildcardQuery(value, method, context); } @Override diff --git a/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java b/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java index 73aa1667f30f4..f5adb70c9fecc 100644 --- a/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java @@ -19,7 +19,6 @@ 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; @@ -70,13 +69,19 @@ private static WildcardQueryBuilder randomWildcardQuery() { @Override protected void doAssertLuceneQuery(WildcardQueryBuilder queryBuilder, Query query, SearchContext context) throws IOException { - assertThat(query, instanceOf(WildcardQuery.class)); - WildcardQuery wildcardQuery = (WildcardQuery) query; - String expectedFieldName = expectedFieldName(queryBuilder.fieldName()); - assertThat(wildcardQuery.getField(), equalTo(expectedFieldName)); - assertThat(wildcardQuery.getTerm().field(), equalTo(expectedFieldName)); - assertThat(wildcardQuery.getTerm().text(), equalTo(queryBuilder.value())); + + if (expectedFieldName.equals(STRING_FIELD_NAME)) { + assertThat(query, instanceOf(WildcardQuery.class)); + WildcardQuery wildcardQuery = (WildcardQuery) query; + + assertThat(wildcardQuery.getField(), equalTo(expectedFieldName)); + assertThat(wildcardQuery.getTerm().field(), equalTo(expectedFieldName)); + assertThat(wildcardQuery.getTerm().text(), equalTo(queryBuilder.value())); + } else { + Query expected = new MatchNoDocsQuery("unknown field [" + expectedFieldName + "]"); + assertEquals(expected, query); + } } public void testIllegalArguments() { @@ -92,7 +97,7 @@ public void testIllegalArguments() { public void testEmptyValue() throws IOException { QueryShardContext context = createShardContext(); context.setAllowUnmappedFields(true); - WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder("doc", ""); + WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(STRING_FIELD_NAME, ""); assertEquals(wildcardQueryBuilder.toQuery(context).getClass(), WildcardQuery.class); } @@ -130,16 +135,6 @@ public void testParseFailsWithMultipleFields() throws IOException { assertEquals("[wildcard] query doesn't support multiple fields, found [user1] and [user2]", e.getMessage()); } - public void testWithMetaDataField() throws IOException { - QueryShardContext context = createShardContext(); - for (String field : new String[]{"field1", "field2"}) { - WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(field, "toto"); - Query query = wildcardQueryBuilder.toQuery(context); - Query expected = new WildcardQuery(new Term(field, "toto")); - assertEquals(expected, query); - } - } - public void testIndexWildcard() throws IOException { QueryShardContext context = createShardContext(); String index = context.getFullyQualifiedIndex().getName();