Exists queries to MatchNoneQueryBuilder when the field is unmapped (#55785)
Co-authored-by: Sivagurunathan Velayutham <sivadeva.93@gmail.com> Closes #54062
This commit is contained in:
parent
4403b69048
commit
0753d9a35c
|
@ -80,6 +80,18 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
|||
return this.fieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws IOException {
|
||||
QueryShardContext context = queryShardContext.convertToShardContext();
|
||||
if (context != null) {
|
||||
Collection<String> fields = getMappedField(context, fieldName);
|
||||
if (fields.isEmpty()) {
|
||||
return new MatchNoneQueryBuilder();
|
||||
}
|
||||
}
|
||||
return super.doRewrite(queryShardContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
|
@ -132,20 +144,10 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
|||
|
||||
public static Query newFilter(QueryShardContext context, String fieldPattern) {
|
||||
|
||||
final FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = (FieldNamesFieldMapper.FieldNamesFieldType) context
|
||||
.getMapperService().fieldType(FieldNamesFieldMapper.NAME);
|
||||
if (fieldNamesFieldType == null) {
|
||||
// can only happen when no types exist, so no docs exist either
|
||||
return Queries.newMatchNoDocsQuery("Missing types in \"" + NAME + "\" query.");
|
||||
}
|
||||
Collection<String> fields = getMappedField(context, fieldPattern);
|
||||
|
||||
final Collection<String> fields;
|
||||
if (context.getObjectMapper(fieldPattern) != null) {
|
||||
// the _field_names field also indexes objects, so we don't have to
|
||||
// do any more work to support exists queries on whole objects
|
||||
fields = Collections.singleton(fieldPattern);
|
||||
} else {
|
||||
fields = context.simpleMatchToIndexNames(fieldPattern);
|
||||
if (fields.isEmpty()) {
|
||||
throw new IllegalStateException("Rewrite first");
|
||||
}
|
||||
|
||||
if (context.indexVersionCreated().before(Version.V_6_1_0)) {
|
||||
|
@ -194,7 +196,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
|||
if (context.getObjectMapper(field) != null) {
|
||||
return newObjectFieldExistsQuery(context, field);
|
||||
}
|
||||
return Queries.newMatchNoDocsQuery("No field \"" + field + "\" exists in mappings.");
|
||||
return Queries.newMatchNoDocsQuery("User requested \"match_none\" query.");
|
||||
}
|
||||
Query filter = fieldType.existsQuery(context);
|
||||
return new ConstantScoreQuery(filter);
|
||||
|
@ -210,6 +212,43 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
|||
return new ConstantScoreQuery(booleanQuery.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get field mapped to this fieldPattern
|
||||
* @return return collection of fields if exists else return empty.
|
||||
*/
|
||||
private static Collection<String> getMappedField(QueryShardContext context, String fieldPattern) {
|
||||
final FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = (FieldNamesFieldMapper.FieldNamesFieldType) context
|
||||
.getMapperService().fieldType(FieldNamesFieldMapper.NAME);
|
||||
|
||||
if (fieldNamesFieldType == null) {
|
||||
// can only happen when no types exist, so no docs exist either
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
final Collection<String> fields;
|
||||
if (context.getObjectMapper(fieldPattern) != null) {
|
||||
// the _field_names field also indexes objects, so we don't have to
|
||||
// do any more work to support exists queries on whole objects
|
||||
fields = Collections.singleton(fieldPattern);
|
||||
} else {
|
||||
fields = context.simpleMatchToIndexNames(fieldPattern);
|
||||
}
|
||||
|
||||
if (fields.size() == 1) {
|
||||
String field = fields.iterator().next();
|
||||
MappedFieldType fieldType = context.getMapperService().fieldType(field);
|
||||
if (fieldType == null) {
|
||||
// The field does not exist as a leaf but could be an object so
|
||||
// check for an object mapper
|
||||
if (context.getObjectMapper(field) == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(fieldName);
|
||||
|
|
|
@ -36,7 +36,6 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
|
||||
|
@ -83,11 +82,9 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
|
|||
assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
}
|
||||
} else if (fields.size() == 1 && mappedFields.size() == 0) {
|
||||
} else if (mappedFields.size() == 0) {
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
MatchNoDocsQuery matchNoDocsQuery = (MatchNoDocsQuery) query;
|
||||
assertThat(matchNoDocsQuery.toString(null),
|
||||
containsString("No field \"" + fields.iterator().next() + "\" exists in mappings."));
|
||||
} else if (fields.size() == 1) {
|
||||
assertThat(query, instanceOf(ConstantScoreQuery.class));
|
||||
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) query;
|
||||
|
@ -128,6 +125,16 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testMustRewrite() throws IOException {
|
||||
QueryShardContext context = createShardContext();
|
||||
context.setAllowUnmappedFields(true);
|
||||
ExistsQueryBuilder queryBuilder = new ExistsQueryBuilder("foo");
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class,
|
||||
() -> queryBuilder.toQuery(context));
|
||||
assertEquals("Rewrite first", e.getMessage());
|
||||
}
|
||||
|
||||
public void testIllegalArguments() {
|
||||
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder((String) null));
|
||||
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder(""));
|
||||
|
|
Loading…
Reference in New Issue