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.
This commit is contained in:
Julie Tibshirani 2020-05-04 09:06:34 -07:00
parent 6da686c7e0
commit 6b5cf1b031
5 changed files with 23 additions and 5 deletions

View File

@ -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 poisonous document can cause all other documents to be rejected if it had a
wrong value. 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. The `value` of the field cannot be changed after it has been set.
[[constant-keyword-params]] [[constant-keyword-params]]

View File

@ -58,11 +58,6 @@ public abstract class ConstantFieldType extends MappedFieldType {
return true; 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} * Return whether the constant value of this field matches the provided {@code pattern}
* as documented in {@link Regex#simpleMatch}. * as documented in {@link Regex#simpleMatch}.

View File

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

View File

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

View File

@ -96,6 +96,13 @@ public class ConstantKeywordFieldTypeTests extends FieldTypeTestCase {
assertEquals(new MatchNoDocsQuery(), ft.prefixQuery("ba", null, null)); 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() { public void testRangeQuery() {
ConstantKeywordFieldType ft = new ConstantKeywordFieldType(); ConstantKeywordFieldType ft = new ConstantKeywordFieldType();
assertEquals(new MatchNoDocsQuery(), ft.rangeQuery(null, null, randomBoolean(), randomBoolean(), null, null, null, null)); assertEquals(new MatchNoDocsQuery(), ft.rangeQuery(null, null, randomBoolean(), randomBoolean(), null, null, null, null));