blob: 6a53d577b21e5a4f487fbbfb349f19930f34f690 [file] [log] [blame]
diff --git a/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java b/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java
index fcae9fc..4c525b7 100644
--- a/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/BooleanQuery.java
@@ -21,9 +21,11 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.BooleanClause.Occur;
@@ -217,13 +219,22 @@ public class BooleanQuery extends Query implements Iterable<BooleanClause> {
builder.setDisableCoord(isCoordDisabled());
builder.setMinimumNumberShouldMatch(getMinimumNumberShouldMatch());
boolean actuallyRewritten = false;
+ final Set<BooleanClause> nonScoring = new HashSet<>(clauses.size());
for (BooleanClause clause : this) {
Query query = clause.getQuery();
Query rewritten = query.rewrite(reader);
if (rewritten != query) {
actuallyRewritten = true;
}
- builder.add(rewritten, clause.getOccur());
+ BooleanClause rewrittenClause = new BooleanClause(rewritten, clause.getOccur());
+ if (!rewrittenClause.isScoring()) {
+ if (!nonScoring.add(rewrittenClause)) {
+ // Drop this duplicate MUST_NOT or FILTER clause
+ actuallyRewritten = true;
+ continue;
+ }
+ }
+ builder.add(rewrittenClause);
}
if (actuallyRewritten) {
return builder.build();
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
index 25c8337..8ee898d 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java
@@ -764,4 +764,60 @@ public class TestBooleanQuery extends LuceneTestCase {
searcher.createNormalizedWeight(bq, false).extractTerms(matchingTerms);
assertEquals(new HashSet<>(Arrays.asList(a, b, c)), matchingTerms);
}
+
+ public void testRewriteToString() throws IOException {
+ try (Directory directory = newDirectory()) {
+ try (IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(null))) {
+ // Just need an empty index so we can create an IndexSearcher below
+ }
+ try (IndexReader indexReader = DirectoryReader.open(directory)) {
+ IndexSearcher searcher = newSearcher(indexReader);
+ Query query = new BooleanQuery.Builder()
+ .add(new TermQuery(new Term("field", "a")), Occur.SHOULD)
+ .add(new TermQuery(new Term("field", "b")), Occur.MUST)
+ .add(new TermQuery(new Term("field", "c")), Occur.MUST_NOT)
+ .add(new TermQuery(new Term("field", "d")), Occur.FILTER)
+ .build();
+ assertEquals("a +b -c #d", searcher.rewrite(query).toString("field"));
+ }
+ }
+ }
+
+ public void testRewriteWithDuplicatesToString() throws IOException {
+ try (Directory directory = newDirectory()) {
+ try (IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(null))) {
+ // Just need an empty index so we can create an IndexSearcher below
+ }
+ try (IndexReader indexReader = DirectoryReader.open(directory)) {
+ IndexSearcher searcher = newSearcher(indexReader);
+ Query query = new BooleanQuery.Builder()
+ .add(new TermQuery(new Term("field", "a")), Occur.SHOULD)
+ .add(new TermQuery(new Term("field", "b")), Occur.MUST)
+ .add(new TermQuery(new Term("field", "c")), Occur.MUST_NOT)
+ .add(new TermQuery(new Term("field", "d")), Occur.FILTER)
+ .add(new TermQuery(new Term("field", "a")), Occur.SHOULD)
+ .add(new TermQuery(new Term("field", "b")), Occur.MUST)
+ .add(new TermQuery(new Term("field", "c")), Occur.MUST_NOT)
+ .add(new TermQuery(new Term("field", "d")), Occur.FILTER)
+ .build();
+ assertEquals("a +b -c #d a +b", searcher.rewrite(query).toString("field"));
+ }
+ }
+ }
+
+ public void testRewriteWithDuplicatesReallyOneClauseToString() throws IOException {
+ try (Directory directory = newDirectory()) {
+ try (IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(null))) {
+ // Just need an empty index so we can create an IndexSearcher below
+ }
+ try (IndexReader indexReader = DirectoryReader.open(directory)) {
+ IndexSearcher searcher = newSearcher(indexReader);
+ Query query = new BooleanQuery.Builder()
+ .add(new TermQuery(new Term("field", "a")), Occur.FILTER)
+ .add(new TermQuery(new Term("field", "a")), Occur.FILTER)
+ .build();
+ assertEquals("ConstantScore(a)^0.0", searcher.rewrite(query).toString("field"));
+ }
+ }
+ }
}