Jelajahi Sumber

For constant_keyword, make sure exists query handles missing values. (#55757)

It's possible for a constant_keyword to have a 'null' value before any documents
are seen that contain a value for the field. In this case, no documents have a
value for the field, and 'exists' queries should return no documents.
Julie Tibshirani 5 tahun lalu
induk
melakukan
bb04fbcd96

+ 4 - 0
docs/reference/mapping/types/constant-keyword.asciidoc

@@ -65,6 +65,10 @@ While this behavior can be convenient, note that it means that a single
 poisonous document can cause all other documents to be rejected if it had a
 wrong value.
 
+Before a value has been provided (either through the mappings or from a
+document), queries on the field will not match any documents. This includes
+ <<query-dsl-exists-query,`exists`>> queries.
+
 The `value` of the field cannot be changed after it has been set.
 
 [[constant-keyword-params]]

+ 0 - 5
server/src/main/java/org/elasticsearch/index/mapper/ConstantFieldType.java

@@ -58,11 +58,6 @@ public abstract class ConstantFieldType extends MappedFieldType {
         return true;
     }
 
-    @Override
-    public final Query existsQuery(QueryShardContext context) {
-        return new MatchAllDocsQuery();
-    }
-
     /**
      * Return whether the constant value of this field matches the provided {@code pattern}
      * as documented in {@link Regex#simpleMatch}.

+ 7 - 0
server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java

@@ -21,6 +21,8 @@ package org.elasticsearch.index.mapper;
 
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.Query;
 import org.elasticsearch.common.lucene.Lucene;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -108,6 +110,11 @@ public class IndexFieldMapper extends MetadataFieldMapper {
             return context.indexMatches(pattern);
         }
 
+        @Override
+        public Query existsQuery(QueryShardContext context) {
+            return new MatchAllDocsQuery();
+        }
+
         @Override
         public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) {
             return new ConstantIndexFieldData.Builder(mapperService -> fullyQualifiedIndexName);

+ 5 - 0
server/src/main/java/org/elasticsearch/index/mapper/TypeFieldMapper.java

@@ -107,6 +107,11 @@ public class TypeFieldMapper extends MetadataFieldMapper {
             return CONTENT_TYPE;
         }
 
+        @Override
+        public Query existsQuery(QueryShardContext context) {
+            return new MatchAllDocsQuery();
+        }
+
         @Override
         public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName) {
             Function<MapperService, String> typeFunction = mapperService -> mapperService.documentMapper().type();

+ 5 - 0
x-pack/plugin/mapper-constant-keyword/src/main/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldMapper.java

@@ -184,6 +184,11 @@ public class ConstantKeywordFieldMapper extends FieldMapper {
             return Regex.simpleMatch(pattern, value);
         }
 
+        @Override
+        public Query existsQuery(QueryShardContext context) {
+            return value != null ? new MatchAllDocsQuery() : new MatchNoDocsQuery();
+        }
+
         @Override
         public Query rangeQuery(
                 Object lowerTerm, Object upperTerm,

+ 7 - 0
x-pack/plugin/mapper-constant-keyword/src/test/java/org/elasticsearch/xpack/constantkeyword/mapper/ConstantKeywordFieldTypeTests.java

@@ -96,6 +96,13 @@ public class ConstantKeywordFieldTypeTests extends FieldTypeTestCase {
         assertEquals(new MatchNoDocsQuery(), ft.prefixQuery("ba", null, null));
     }
 
+    public void testExistsQuery() {
+        ConstantKeywordFieldType ft = new ConstantKeywordFieldType();
+        assertEquals(new MatchNoDocsQuery(), ft.existsQuery(null));
+        ft.setValue("foo");
+        assertEquals(new MatchAllDocsQuery(), ft.existsQuery(null));
+    }
+
     public void testRangeQuery() {
         ConstantKeywordFieldType ft = new ConstantKeywordFieldType();
         assertEquals(new MatchNoDocsQuery(), ft.rangeQuery(null, null, randomBoolean(), randomBoolean(), null, null, null, null));