Fix exists query on unmapped field in query_string (#58804)

Since #55785, exists queries rewrite to MatchNoneQueryBuilder when the field is unmapped.
This change also introduced a bug in the `query_string` query, using an unmapped field
like `_exists_:foo` throws an exception if the field is unmapped. This commit avoids the
exception if the query is built outside of an `ExistsQueryBuilder`.

Closes #58737
This commit is contained in:
Jim Ferenczi 2020-07-02 21:51:28 +02:00 committed by jimczi
parent 605e24ed7c
commit a4e08acdd1
5 changed files with 13 additions and 6 deletions

View File

@ -24,6 +24,7 @@ import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.Version;
@ -139,15 +140,19 @@ public class ExistsQueryBuilder extends AbstractQueryBuilder<ExistsQueryBuilder>
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
return newFilter(context, fieldName);
return newFilter(context, fieldName, true);
}
public static Query newFilter(QueryShardContext context, String fieldPattern) {
public static Query newFilter(QueryShardContext context, String fieldPattern, boolean checkRewrite) {
Collection<String> fields = getMappedField(context, fieldPattern);
if (fields.isEmpty()) {
throw new IllegalStateException("Rewrite first");
if (checkRewrite) {
throw new IllegalStateException("Rewrite first");
} else {
return new MatchNoDocsQuery("unmapped field:" + fieldPattern);
}
}
if (context.indexVersionCreated().before(Version.V_6_1_0)) {

View File

@ -94,7 +94,7 @@ public class LegacyGeoShapeQueryProcessor implements QueryProcessor {
// before, including creating lucene fieldcache (!)
// in this case, execute disjoint as exists && !intersects
BooleanQuery.Builder bool = new BooleanQuery.Builder();
Query exists = ExistsQueryBuilder.newFilter(context, fieldName);
Query exists = ExistsQueryBuilder.newFilter(context, fieldName,false);
Query intersects = prefixTreeStrategy.makeQuery(getArgs(shape, ShapeRelation.INTERSECTS));
bool.add(exists, BooleanClause.Occur.MUST);
bool.add(intersects, BooleanClause.Occur.MUST_NOT);

View File

@ -486,7 +486,7 @@ public class RangeQueryBuilder extends AbstractQueryBuilder<RangeQueryBuilder> i
}
// Exists query would fail if the fieldNames field is disabled.
if (fieldNamesFieldType.isEnabled()) {
return ExistsQueryBuilder.newFilter(context, fieldName);
return ExistsQueryBuilder.newFilter(context, fieldName, false);
}
}
MappedFieldType mapper = context.fieldMapper(this.fieldName);

View File

@ -632,7 +632,7 @@ public class QueryStringQueryParser extends XQueryParser {
return new WildcardQuery(new Term(fieldName, "*"));
}
return ExistsQueryBuilder.newFilter(context, fieldName);
return ExistsQueryBuilder.newFilter(context, fieldName, false);
}
@Override

View File

@ -134,6 +134,8 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
IllegalStateException e = expectThrows(IllegalStateException.class,
() -> queryBuilder.toQuery(context));
assertEquals("Rewrite first", e.getMessage());
Query ret = ExistsQueryBuilder.newFilter(context, "foo", false);
assertThat(ret, instanceOf(MatchNoDocsQuery.class));
}
public void testIllegalArguments() {