瀏覽代碼

Make empty string searches be consistent with case (in)sensitivity (#110833)

If we determine that the searchable term is completely empty, we switch back to a regular term query. This way we return the same docs as expected when we do a case sensitive search.

closes: #108968
Benjamin Trent 1 年之前
父節點
當前提交
28c7cbccce

+ 5 - 0
docs/changelog/110833.yaml

@@ -0,0 +1,5 @@
+pr: 110833
+summary: Make empty string searches be consistent with case (in)sensitivity
+area: Search
+type: bug
+issues: []

+ 37 - 0
rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/search/171_term_query.yml

@@ -0,0 +1,37 @@
+---
+"case insensitive term query on blank keyword is consistent":
+  - requires:
+      cluster_features: [ "gte_v8.16.0" ]
+      reason: "query consistency bug fix in 8.16.0"
+  - do:
+      indices.create:
+          index: index_with_blank_keyword
+          body:
+              settings:
+                  number_of_shards: 1
+              mappings:
+                  properties:
+                      keyword_field:
+                          type: keyword
+  - do:
+      bulk:
+          refresh: true
+          body:
+              - '{"index": {"_index": "index_with_blank_keyword", "_id": "1"}}'
+              - '{"keyword_field": ""}'
+
+  - do:
+      search:
+          rest_total_hits_as_int: true
+          index: index_with_blank_keyword
+          body: {"query" : {"term" : {"keyword_field" : {"value":  ""}}}}
+
+  - match: { hits.total: 1 }
+
+  - do:
+      search:
+        rest_total_hits_as_int: true
+        index: index_with_blank_keyword
+        body: { "query": { "term": { "keyword_field": {"value": "", "case_insensitive": true } } } }
+
+  - match: { hits.total: 1 }

+ 7 - 1
server/src/main/java/org/elasticsearch/index/mapper/TermBasedFieldType.java

@@ -45,7 +45,13 @@ public abstract class TermBasedFieldType extends SimpleMappedFieldType {
     @Override
     public Query termQueryCaseInsensitive(Object value, SearchExecutionContext context) {
         failIfNotIndexed();
-        return AutomatonQueries.caseInsensitiveTermQuery(new Term(name(), indexedValueForSearch(value)));
+        final BytesRef valueForSearch = indexedValueForSearch(value);
+        // check if valueForSearch is the same as an empty string
+        // if we have a length of zero, just do a regular term query
+        if (valueForSearch.length == 0) {
+            return termQuery(value, context);
+        }
+        return AutomatonQueries.caseInsensitiveTermQuery(new Term(name(), valueForSearch));
     }
 
     @Override