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;
|
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
|
@Override
|
||||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
builder.startObject(NAME);
|
builder.startObject(NAME);
|
||||||
|
@ -132,20 +144,10 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
||||||
|
|
||||||
public static Query newFilter(QueryShardContext context, String fieldPattern) {
|
public static Query newFilter(QueryShardContext context, String fieldPattern) {
|
||||||
|
|
||||||
final FieldNamesFieldMapper.FieldNamesFieldType fieldNamesFieldType = (FieldNamesFieldMapper.FieldNamesFieldType) context
|
Collection<String> fields = getMappedField(context, fieldPattern);
|
||||||
.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.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Collection<String> fields;
|
if (fields.isEmpty()) {
|
||||||
if (context.getObjectMapper(fieldPattern) != null) {
|
throw new IllegalStateException("Rewrite first");
|
||||||
// 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 (context.indexVersionCreated().before(Version.V_6_1_0)) {
|
if (context.indexVersionCreated().before(Version.V_6_1_0)) {
|
||||||
|
@ -194,7 +196,7 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
||||||
if (context.getObjectMapper(field) != null) {
|
if (context.getObjectMapper(field) != null) {
|
||||||
return newObjectFieldExistsQuery(context, field);
|
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);
|
Query filter = fieldType.existsQuery(context);
|
||||||
return new ConstantScoreQuery(filter);
|
return new ConstantScoreQuery(filter);
|
||||||
|
@ -210,6 +212,43 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
|
||||||
return new ConstantScoreQuery(booleanQuery.build());
|
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
|
@Override
|
||||||
protected int doHashCode() {
|
protected int doHashCode() {
|
||||||
return Objects.hash(fieldName);
|
return Objects.hash(fieldName);
|
||||||
|
|
|
@ -36,7 +36,6 @@ import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
|
||||||
|
@ -83,11 +82,9 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
|
||||||
assertThat(booleanClause.getOccur(), equalTo(BooleanClause.Occur.SHOULD));
|
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));
|
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||||
MatchNoDocsQuery matchNoDocsQuery = (MatchNoDocsQuery) query;
|
MatchNoDocsQuery matchNoDocsQuery = (MatchNoDocsQuery) query;
|
||||||
assertThat(matchNoDocsQuery.toString(null),
|
|
||||||
containsString("No field \"" + fields.iterator().next() + "\" exists in mappings."));
|
|
||||||
} else if (fields.size() == 1) {
|
} else if (fields.size() == 1) {
|
||||||
assertThat(query, instanceOf(ConstantScoreQuery.class));
|
assertThat(query, instanceOf(ConstantScoreQuery.class));
|
||||||
ConstantScoreQuery constantScoreQuery = (ConstantScoreQuery) query;
|
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() {
|
public void testIllegalArguments() {
|
||||||
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder((String) null));
|
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder((String) null));
|
||||||
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder(""));
|
expectThrows(IllegalArgumentException.class, () -> new ExistsQueryBuilder(""));
|
||||||
|
|
Loading…
Reference in New Issue