Rewrite match_all inside must_not (#85999)

A must_not with a match_all clause inside a bool query is currently not rewritten to a match_none query. This means that running a boolean query with "must_not":[{"terms":{"_tier":["data_frozen","data_cold"]}] is currently not rewritten as match_none on a cold/frozen tier node.
This commit is contained in:
Yannick Welsch 2022-04-20 08:58:19 +02:00 committed by GitHub
parent 718a241449
commit 4c47daa8d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 9 deletions

View file

@ -0,0 +1,5 @@
pr: 85999
summary: Rewrite `match_all` inside `must_not`
area: Search
type: bug
issues: []

View file

@ -21,6 +21,7 @@ import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.ConstantScoreQueryBuilder; import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
import org.elasticsearch.index.query.DisMaxQueryBuilder; import org.elasticsearch.index.query.DisMaxQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder; import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchNoneQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder; import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.Operator;
@ -84,10 +85,10 @@ public class QueryBuilderBWCIT extends AbstractFullClusterRestartTestCase {
""", new RangeQueryBuilder("long_field").from(1).to(9)); """, new RangeQueryBuilder("long_field").from(1).to(9));
addCandidate( addCandidate(
""" """
"bool": { "must_not": [{"match_all": {}}], "must": [{"match_all": {}}], "filter": [{"match_all": {}}], \ "bool": { "must_not": [{"match_none": {}}], "must": [{"match_all": {}}], "filter": [{"match_all": {}}], \
"should": [{"match_all": {}}]} "should": [{"match_all": {}}]}
""", """,
new BoolQueryBuilder().mustNot(new MatchAllQueryBuilder()) new BoolQueryBuilder().mustNot(new MatchNoneQueryBuilder())
.must(new MatchAllQueryBuilder()) .must(new MatchAllQueryBuilder())
.filter(new MatchAllQueryBuilder()) .filter(new MatchAllQueryBuilder())
.should(new MatchAllQueryBuilder()) .should(new MatchAllQueryBuilder())

View file

@ -29,9 +29,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream;
import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded; import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded;
import static org.elasticsearch.search.SearchModule.INDICES_MAX_NESTED_DEPTH_SETTING; import static org.elasticsearch.search.SearchModule.INDICES_MAX_NESTED_DEPTH_SETTING;
@ -385,11 +383,10 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
} }
// lets do some early termination and prevent any kind of rewriting if we have a mandatory query that is a MatchNoneQueryBuilder // lets do some early termination and prevent any kind of rewriting if we have a mandatory query that is a MatchNoneQueryBuilder
Optional<QueryBuilder> any = Stream.concat(newBuilder.mustClauses.stream(), newBuilder.filterClauses.stream()) if (newBuilder.mustClauses.stream().anyMatch(b -> b instanceof MatchNoneQueryBuilder)
.filter(b -> b instanceof MatchNoneQueryBuilder) || newBuilder.filterClauses.stream().anyMatch(b -> b instanceof MatchNoneQueryBuilder)
.findAny(); || newBuilder.mustNotClauses.stream().anyMatch(b -> b instanceof MatchAllQueryBuilder)) {
if (any.isPresent()) { return new MatchNoneQueryBuilder();
return any.get();
} }
if (changed) { if (changed) {

View file

@ -425,6 +425,12 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder = new BoolQueryBuilder();
rewritten = Rewriteable.rewrite(boolQueryBuilder, createSearchExecutionContext()); rewritten = Rewriteable.rewrite(boolQueryBuilder, createSearchExecutionContext());
assertNotEquals(new MatchNoneQueryBuilder(), rewritten); assertNotEquals(new MatchNoneQueryBuilder(), rewritten);
boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.filter(new TermQueryBuilder(TEXT_FIELD_NAME, "bar"));
boolQueryBuilder.mustNot(new WrapperQueryBuilder(new WrapperQueryBuilder(new MatchAllQueryBuilder().toString()).toString()));
rewritten = boolQueryBuilder.rewrite(createSearchExecutionContext());
assertEquals(new MatchNoneQueryBuilder(), rewritten);
} }
@Override @Override