From 66098e0bf49698cf78a1ef10396ec8c4b061815c Mon Sep 17 00:00:00 2001 From: markharwood Date: Wed, 12 Aug 2020 10:44:52 +0100 Subject: [PATCH] Search fix: query_string regex/wildcard searches not working on wildcard fields (#60959) (#61010) The Query string parser was not delegating the construction of wildcard/regex queries to the underlying field type. The wildcard field has special data structures and queries that operate on them so cannot rely on the basic regex/wildcard queries that were being used for other fields. Closes #60957 --- .../index/search/QueryStringQueryParser.java | 24 +++++++---- .../test/wildcard/10_wildcard_basic.yml | 40 +++++++++++++++++++ 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java b/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java index 4260df0a6e6..8120dc68a22 100644 --- a/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java +++ b/server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java @@ -43,6 +43,7 @@ import org.apache.lucene.search.spans.SpanNearQuery; import org.apache.lucene.search.spans.SpanOrQuery; import org.apache.lucene.search.spans.SpanQuery; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.automaton.RegExp; import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.unit.Fuzziness; @@ -669,15 +670,19 @@ public class QueryStringQueryParser extends XQueryParser { // effectively, we check if a field exists or not return existsQuery(field); } - String indexedNameField = field; Analyzer oldAnalyzer = getAnalyzer(); try { MappedFieldType currentFieldType = queryBuilder.context.fieldMapper(field); - if (currentFieldType != null) { - setAnalyzer(forceAnalyzer == null ? queryBuilder.context.getSearchAnalyzer(currentFieldType) : forceAnalyzer); - indexedNameField = currentFieldType.name(); + if (currentFieldType == null) { + return newUnmappedFieldQuery(field); + } + if (forceAnalyzer != null && + (analyzeWildcard || currentFieldType.getTextSearchInfo().isTokenized())) { + setAnalyzer(forceAnalyzer); + return super.getWildcardQuery(currentFieldType.name(), termStr); } - return super.getWildcardQuery(indexedNameField, termStr); + + return currentFieldType.wildcardQuery(termStr, getMultiTermRewriteMethod(), context); } catch (RuntimeException e) { if (lenient) { return newLenientFieldQuery(field, e); @@ -722,9 +727,12 @@ public class QueryStringQueryParser extends XQueryParser { if (currentFieldType == null) { return newUnmappedFieldQuery(field); } - setAnalyzer(forceAnalyzer == null ? queryBuilder.context.getSearchAnalyzer(currentFieldType) : forceAnalyzer); - Query query = super.getRegexpQuery(field, termStr); - return query; + if (forceAnalyzer != null) { + setAnalyzer(forceAnalyzer); + return super.getRegexpQuery(field, termStr); + } + return currentFieldType.regexpQuery(termStr, RegExp.ALL, getMaxDeterminizedStates(), + getMultiTermRewriteMethod(), context); } catch (RuntimeException e) { if (lenient) { return newLenientFieldQuery(field, e); diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/wildcard/10_wildcard_basic.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/wildcard/10_wildcard_basic.yml index 5ddd2e84a65..23d9fbad483 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/wildcard/10_wildcard_basic.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/wildcard/10_wildcard_basic.yml @@ -158,6 +158,46 @@ setup: - match: {hits.total.value: 1} +--- +"Query_string prefix query": + - do: + search: + body: + track_total_hits: true + query: + query_string: + query: "hello*" + default_field: "my_wildcard" + + + - match: {hits.total.value: 1} +--- +"Query_string wildcard query": + - do: + search: + body: + track_total_hits: true + query: + query_string: + query: "*orld" + default_field: "my_wildcard" + + + - match: {hits.total.value: 3} +--- +"Query_string regex query": + - do: + search: + body: + track_total_hits: true + query: + query_string: + query: "/hello.*/" + default_field: "my_wildcard" + + + - match: {hits.total.value: 1} + --- "Term query on wildcard field": - do: