Browse Source

Search fix: query_string regex/wildcard searches not working on wildcard fields (#60959)

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
markharwood 5 years ago
parent
commit
4bb5b36376

+ 16 - 8
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);

+ 40 - 0
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: