Rewrite queries with no SHOULD clauses and minimumShouldMatch > 0 to a MatchNoDocsQuery.

Closes #14026
This commit is contained in:
Adrien Grand 2024-11-29 14:47:44 +01:00
parent f9869b54d5
commit 06a320a53e
2 changed files with 28 additions and 18 deletions

View File

@ -604,23 +604,20 @@ public class BooleanQuery extends Query implements Iterable<BooleanClause> {
// Important(this can only be processed after nested clauses have been flattened)
{
final Collection<Query> shoulds = clauseSets.get(Occur.SHOULD);
if (shoulds.size() > 0) {
if (shoulds.size() < minimumNumberShouldMatch) {
return new MatchNoDocsQuery("SHOULD clause count less than minimumNumberShouldMatch");
}
if (shoulds.size() == minimumNumberShouldMatch) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (BooleanClause clause : clauses) {
if (clause.occur() == Occur.SHOULD) {
builder.add(clause.query(), Occur.MUST);
} else {
builder.add(clause);
}
if (shoulds.size() < minimumNumberShouldMatch) {
return new MatchNoDocsQuery("SHOULD clause count less than minimumNumberShouldMatch");
}
if (shoulds.size() > 0 && shoulds.size() == minimumNumberShouldMatch) {
BooleanQuery.Builder builder = new BooleanQuery.Builder();
for (BooleanClause clause : clauses) {
if (clause.occur() == Occur.SHOULD) {
builder.add(clause.query(), Occur.MUST);
} else {
builder.add(clause);
}
return builder.build();
}
return builder.build();
}
}

View File

@ -401,14 +401,12 @@ public class TestBooleanRewrites extends LuceneTestCase {
bq =
new BooleanQuery.Builder()
.setMinimumNumberShouldMatch(random().nextInt(5))
.add(new TermQuery(new Term("foo", "bar")), Occur.MUST)
.add(new TermQuery(new Term("foo", "baz")), Occur.MUST)
.add(new MatchAllDocsQuery(), Occur.FILTER)
.build();
Query expected =
new BooleanQuery.Builder()
.setMinimumNumberShouldMatch(bq.getMinimumNumberShouldMatch())
.add(new TermQuery(new Term("foo", "bar")), Occur.MUST)
.add(new TermQuery(new Term("foo", "baz")), Occur.MUST)
.build();
@ -476,7 +474,22 @@ public class TestBooleanRewrites extends LuceneTestCase {
Query query = randomBooleanQuery(random());
final TopDocs td1 = searcher1.search(query, 100);
final TopDocs td2 = searcher2.search(query, 100);
assertEquals(td1, td2);
try {
assertEquals(td1, td2);
} catch (AssertionError e) {
System.out.println(query);
Query rewritten = query;
do {
query = rewritten;
rewritten = query.rewrite(searcher1);
System.out.println(rewritten);
TopDocs tdx = searcher2.search(rewritten, 100);
if (td2.totalHits.value() != tdx.totalHits.value()) {
System.out.println("Bad");
}
} while (query != rewritten);
throw e;
}
}
searcher1.getIndexReader().close();