From cf40cd4fd8cf1f35a5e4c2b17c82249ea68b94c8 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 25 Sep 2018 12:53:14 -0700 Subject: [PATCH 1/3] Delegate wildcard query creation to MappedFieldType. --- .../index/mapper/MappedFieldType.java | 12 ++++++++++ .../index/query/WildcardQueryBuilder.java | 22 +++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) 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 82a601de05e94..86c4380409dcf 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -30,10 +30,13 @@ import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.ConstantScoreQuery; +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.search.TermInSetQuery; import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.Nullable; @@ -345,6 +348,15 @@ 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) { + Query termQuery = termQuery(value, context); + if (termQuery instanceof MatchNoDocsQuery || termQuery instanceof MatchAllDocsQuery) { + return termQuery; + } + Term term = MappedFieldType.extractTerm(termQuery); + return new WildcardQuery(term); + } + public Query regexpQuery(String value, int flags, int maxDeterminizedStates, @Nullable MultiTermQuery.RewriteMethod method, QueryShardContext context) { throw new QueryShardException(context, "Can only use regexp queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); } 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 2136e030dbdb1..489286d309472 100644 --- a/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java @@ -20,8 +20,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.MultiTermQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.WildcardQuery; @@ -185,20 +183,20 @@ public static WildcardQueryBuilder fromXContent(XContentParser parser) throws IO @Override protected Query doToQuery(QueryShardContext context) throws IOException { MappedFieldType fieldType = context.fieldMapper(fieldName); - Term term; + + Query query; if (fieldType == null) { - term = new Term(fieldName, BytesRefs.toBytesRef(value)); + Term term = new Term(fieldName, BytesRefs.toBytesRef(value)); + query = new WildcardQuery(term); } else { - Query termQuery = fieldType.termQuery(value, context); - if (termQuery instanceof MatchNoDocsQuery || termQuery instanceof MatchAllDocsQuery) { - return termQuery; - } - term = MappedFieldType.extractTerm(termQuery); + query = fieldType.wildcardQuery(value, context); } - WildcardQuery query = new WildcardQuery(term); - MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod(rewrite, null, LoggingDeprecationHandler.INSTANCE); - QueryParsers.setRewriteMethod(query, rewriteMethod); + if (query instanceof MultiTermQuery) { + MultiTermQuery.RewriteMethod rewriteMethod = QueryParsers.parseRewriteMethod( + rewrite, null, LoggingDeprecationHandler.INSTANCE); + QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod); + } return query; } From f2d621f1790342d616559fce1f7df0aef6e9ac02 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 25 Sep 2018 13:50:13 -0700 Subject: [PATCH 2/3] Disallow wildcard queries on collation fields. --- .../index/mapper/ICUCollationKeywordFieldMapper.java | 12 ++++++++---- .../index/mapper/CollationFieldTypeTests.java | 8 ++++++++ 2 files changed, 16 insertions(+), 4 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 0235e6e81368f..a89163b564d49 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 @@ -23,7 +23,6 @@ import com.ibm.icu.text.RawCollationKey; import com.ibm.icu.text.RuleBasedCollator; import com.ibm.icu.util.ULocale; - import org.apache.lucene.document.Field; import org.apache.lucene.document.SortedSetDocValuesField; import org.apache.lucene.index.IndexOptions; @@ -158,18 +157,23 @@ protected BytesRef indexedValueForSearch(Object value) { @Override public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("[fuzzy] queries are not supported on [" + CONTENT_TYPE + "] fields."); } @Override public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("[prefix] queries are not supported on [" + CONTENT_TYPE + "] fields."); + } + + @Override + public Query wildcardQuery(String value, QueryShardContext context) { + throw new UnsupportedOperationException("[wildcard] queries are not supported on [" + CONTENT_TYPE + "] fields."); } @Override public Query regexpQuery(String value, int flags, int maxDeterminizedStates, MultiTermQuery.RewriteMethod method, QueryShardContext context) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("[regexp] queries are not supported on [" + CONTENT_TYPE + "] fields."); } public static DocValueFormat COLLATE_FORMAT = new DocValueFormat() { 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 71d8f25bf9f3b..f90971412358d 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 @@ -121,6 +121,14 @@ public void testPrefixQuery() { () -> ft.prefixQuery("prefix", null, null)); } + public void testWildcardQuery() { + MappedFieldType ft = createDefaultFieldType(); + ft.setName("field"); + ft.setIndexOptions(IndexOptions.DOCS); + expectThrows(UnsupportedOperationException.class, + () -> ft.wildcardQuery("foo*", null)); + } + public void testRangeQuery() { MappedFieldType ft = createDefaultFieldType(); ft.setName("field"); From dcd8502604c8c11a6793616f874c59abfb7c98c0 Mon Sep 17 00:00:00 2001 From: Julie Tibshirani Date: Tue, 25 Sep 2018 16:56:01 -0700 Subject: [PATCH 3/3] Disallow wildcard queries on non-string fields. For backwards compatibility, we maintain support on the `_index` field. --- .../index/mapper/IndexFieldMapper.java | 11 ++++++++++- .../elasticsearch/index/mapper/MappedFieldType.java | 10 +--------- .../elasticsearch/index/mapper/StringFieldType.java | 13 +++++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) 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 bb048ab9afac4..fac00907980fd 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java @@ -150,8 +150,17 @@ public Query termsQuery(List values, QueryShardContext context) { + " vs. " + values); } + @Override + public Query wildcardQuery(String value, QueryShardContext context) { + if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) { + return Queries.newMatchAllQuery(); + } else { + return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + value); + } + } + private boolean isSameIndex(Object value, String indexName) { - String pattern = value instanceof BytesRef ? pattern = ((BytesRef) value).utf8ToString() : value.toString(); + String pattern = value instanceof BytesRef ? ((BytesRef) value).utf8ToString() : value.toString(); return Regex.simpleMatch(pattern, indexName); } 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 86c4380409dcf..e4aeee0e6ff31 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -30,13 +30,10 @@ import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BoostQuery; import org.apache.lucene.search.ConstantScoreQuery; -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.search.TermInSetQuery; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.util.BytesRef; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.Nullable; @@ -349,12 +346,7 @@ public Query prefixQuery(String value, @Nullable MultiTermQuery.RewriteMethod me } public Query wildcardQuery(String value, 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); + throw new QueryShardException(context, "Can only use wildcard queries on keyword and text fields - not on [" + name + "] which is of type [" + typeName() + "]"); } public Query regexpQuery(String value, int flags, int maxDeterminizedStates, @Nullable MultiTermQuery.RewriteMethod method, QueryShardContext context) { 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 37834b93a1e0f..857c588717b2a 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java @@ -22,6 +22,8 @@ import java.util.List; import org.apache.lucene.index.Term; +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; @@ -29,6 +31,7 @@ import org.apache.lucene.search.Query; import org.apache.lucene.search.RegexpQuery; 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; @@ -74,6 +77,16 @@ public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, Quer return query; } + @Override + public Query wildcardQuery(String value, 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); + } + @Override public Query regexpQuery(String value, int flags, int maxDeterminizedStates, MultiTermQuery.RewriteMethod method, QueryShardContext context) {