diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 2a853dfeaed..766b7fa6d02 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -135,6 +135,9 @@ API Changes * LUCENE-6855: CachingWrapperQuery is deprecated and will be removed in 6.0. (Adrien Grand) +* LUCENE-6870: DisjunctionMaxQuery#add is now deprecated, clauses should all be + provided at construction time. (Adrien Grand) + Optimizations * LUCENE-6708: TopFieldCollector does not compute the score several times on the diff --git a/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java b/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java index 5ee288d6d98..1b1d0b00b8d 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/DisjunctionMaxQuery.java @@ -18,7 +18,9 @@ package org.apache.lucene.search; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -45,58 +47,36 @@ import org.apache.lucene.index.Term; public final class DisjunctionMaxQuery extends Query implements Iterable { /* The subqueries */ - private ArrayList disjuncts = new ArrayList<>(); + private final Query[] disjuncts; /* Multiple of the non-max disjunct scores added into our final score. Non-zero values support tie-breaking. */ - private float tieBreakerMultiplier = 0.0f; - - /** Creates a new empty DisjunctionMaxQuery. Use add() to add the subqueries. - * @param tieBreakerMultiplier the score of each non-maximum disjunct for a document is multiplied by this weight - * and added into the final score. If non-zero, the value should be small, on the order of 0.1, which says that - * 10 occurrences of word in a lower-scored field that is also in a higher scored field is just as good as a unique - * word in the lower scored field (i.e., one that is not in any higher scored field. - */ - public DisjunctionMaxQuery(float tieBreakerMultiplier) { - this.tieBreakerMultiplier = tieBreakerMultiplier; - } + private final float tieBreakerMultiplier; /** * Creates a new DisjunctionMaxQuery * @param disjuncts a {@code Collection} of all the disjuncts to add - * @param tieBreakerMultiplier the weight to give to each matching non-maximum disjunct + * @param tieBreakerMultiplier the score of each non-maximum disjunct for a document is multiplied by this weight + * and added into the final score. If non-zero, the value should be small, on the order of 0.1, which says that + * 10 occurrences of word in a lower-scored field that is also in a higher scored field is just as good as a unique + * word in the lower scored field (i.e., one that is not in any higher scored field. */ public DisjunctionMaxQuery(Collection disjuncts, float tieBreakerMultiplier) { Objects.requireNonNull(disjuncts, "Collection of Querys must not be null"); this.tieBreakerMultiplier = tieBreakerMultiplier; - add(disjuncts); - } - - /** Add a subquery to this disjunction - * @param query the disjunct added - */ - public void add(Query query) { - disjuncts.add(Objects.requireNonNull(query, "Query must not be null")); - } - - /** Add a collection of disjuncts to this disjunction - * via {@code Iterable} - * @param disjuncts a collection of queries to add as disjuncts. - */ - public void add(Collection disjuncts) { - this.disjuncts.addAll(Objects.requireNonNull(disjuncts, "Query connection must not be null")); + this.disjuncts = disjuncts.toArray(new Query[disjuncts.size()]); } /** @return An {@code Iterator} over the disjuncts */ @Override public Iterator iterator() { - return disjuncts.iterator(); + return getDisjuncts().iterator(); } /** * @return the disjuncts. */ - public ArrayList getDisjuncts() { - return disjuncts; + public List getDisjuncts() { + return Collections.unmodifiableList(Arrays.asList(disjuncts)); } /** @@ -215,21 +195,22 @@ public final class DisjunctionMaxQuery extends Query implements Iterable * @return an optimized copy of us (which may not be a copy if there is nothing to optimize) */ @Override public Query rewrite(IndexReader reader) throws IOException { - int numDisjunctions = disjuncts.size(); - if (numDisjunctions == 1) { - return disjuncts.get(0); + if (disjuncts.length == 1) { + return disjuncts[0]; } - DisjunctionMaxQuery rewritten = new DisjunctionMaxQuery(tieBreakerMultiplier); + boolean actuallyRewritten = false; + List rewrittenDisjuncts = new ArrayList<>(); for (Query sub : disjuncts) { Query rewrittenSub = sub.rewrite(reader); actuallyRewritten |= rewrittenSub != sub; - rewritten.add(rewrittenSub); + rewrittenDisjuncts.add(rewrittenSub); } if (actuallyRewritten) { - return rewritten; + return new DisjunctionMaxQuery(rewrittenDisjuncts, tieBreakerMultiplier); } + return super.rewrite(reader); } @@ -241,16 +222,15 @@ public final class DisjunctionMaxQuery extends Query implements Iterable public String toString(String field) { StringBuilder buffer = new StringBuilder(); buffer.append("("); - int numDisjunctions = disjuncts.size(); - for (int i = 0 ; i < numDisjunctions; i++) { - Query subquery = disjuncts.get(i); + for (int i = 0 ; i < disjuncts.length; i++) { + Query subquery = disjuncts[i]; if (subquery instanceof BooleanQuery) { // wrap sub-bools in parens buffer.append("("); buffer.append(subquery.toString(field)); buffer.append(")"); } else buffer.append(subquery.toString(field)); - if (i != numDisjunctions-1) buffer.append(" | "); + if (i != disjuncts.length-1) buffer.append(" | "); } buffer.append(")"); if (tieBreakerMultiplier != 0.0f) { @@ -270,7 +250,7 @@ public final class DisjunctionMaxQuery extends Query implements Iterable DisjunctionMaxQuery other = (DisjunctionMaxQuery)o; return super.equals(o) && this.tieBreakerMultiplier == other.tieBreakerMultiplier - && this.disjuncts.equals(other.disjuncts); + && Arrays.equals(disjuncts, other.disjuncts); } /** Compute a hash code for hashing us @@ -280,7 +260,7 @@ public final class DisjunctionMaxQuery extends Query implements Iterable public int hashCode() { int h = super.hashCode(); h = 31 * h + Float.floatToIntBits(tieBreakerMultiplier); - h = 31 * h + disjuncts.hashCode(); + h = 31 * h + Arrays.hashCode(disjuncts); return h; } 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 355e591a8bb..3560d06831a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQuery.java @@ -250,9 +250,9 @@ public class TestBooleanQuery extends LuceneTestCase { q.add(pq, BooleanClause.Occur.MUST); assertEquals(0, s.search(q.build(), 10).totalHits); - DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(1.0f); - dmq.add(new TermQuery(new Term("field", "a"))); - dmq.add(pq); + DisjunctionMaxQuery dmq = new DisjunctionMaxQuery( + Arrays.asList(new TermQuery(new Term("field", "a")), pq), + 1.0f); assertEquals(1, s.search(dmq, 10).totalHits); r.close(); diff --git a/lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java b/lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java index 8031c691d51..fab966d6871 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestComplexExplanations.java @@ -17,6 +17,10 @@ package org.apache.lucene.search; * limitations under the License. */ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.similarities.ClassicSimilarity; @@ -77,33 +81,33 @@ public class TestComplexExplanations extends BaseExplanationTestCase { t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2})); q.add(new BoostQuery(t, 30), Occur.SHOULD); - - DisjunctionMaxQuery dm = new DisjunctionMaxQuery(0.2f); - dm.add(snear(st("w2"), + + List disjuncts = new ArrayList<>(); + disjuncts.add(snear(st("w2"), sor("w5","zz"), 4, true)); - dm.add(new TermQuery(new Term(FIELD, "QQ"))); + disjuncts.add(new TermQuery(new Term(FIELD, "QQ"))); BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();; xxYYZZ.add(new TermQuery(new Term(FIELD, "xx")), Occur.SHOULD); xxYYZZ.add(new TermQuery(new Term(FIELD, "yy")), Occur.SHOULD); xxYYZZ.add(new TermQuery(new Term(FIELD, "zz")), Occur.MUST_NOT); - dm.add(xxYYZZ.build()); + disjuncts.add(xxYYZZ.build()); BooleanQuery.Builder xxW1 = new BooleanQuery.Builder();; xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT); xxW1.add(new TermQuery(new Term(FIELD, "w1")), Occur.MUST_NOT); - dm.add(xxW1.build()); + disjuncts.add(xxW1.build()); - DisjunctionMaxQuery dm2 = new DisjunctionMaxQuery(0.5f); - dm2.add(new TermQuery(new Term(FIELD, "w1"))); - dm2.add(new TermQuery(new Term(FIELD, "w2"))); - dm2.add(new TermQuery(new Term(FIELD, "w3"))); - dm.add(dm2); + List disjuncts2 = new ArrayList<>(); + disjuncts2.add(new TermQuery(new Term(FIELD, "w1"))); + disjuncts2.add(new TermQuery(new Term(FIELD, "w2"))); + disjuncts2.add(new TermQuery(new Term(FIELD, "w3"))); + disjuncts.add(new DisjunctionMaxQuery(disjuncts2, 0.5f)); - q.add(dm, Occur.SHOULD); + q.add(new DisjunctionMaxQuery(disjuncts, 0.2f), Occur.SHOULD); BooleanQuery.Builder b = new BooleanQuery.Builder();; b.setMinimumNumberShouldMatch(2); @@ -138,32 +142,34 @@ public class TestComplexExplanations extends BaseExplanationTestCase { t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2})); q.add(new BoostQuery(t, -20), Occur.SHOULD); - DisjunctionMaxQuery dm = new DisjunctionMaxQuery(0.2f); - dm.add(snear(st("w2"), + List disjuncts = new ArrayList<>(); + disjuncts.add(snear(st("w2"), sor("w5","zz"), 4, true)); - dm.add(new TermQuery(new Term(FIELD, "QQ"))); + disjuncts.add(new TermQuery(new Term(FIELD, "QQ"))); BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();; xxYYZZ.add(new TermQuery(new Term(FIELD, "xx")), Occur.SHOULD); xxYYZZ.add(new TermQuery(new Term(FIELD, "yy")), Occur.SHOULD); xxYYZZ.add(new TermQuery(new Term(FIELD, "zz")), Occur.MUST_NOT); - dm.add(xxYYZZ.build()); + disjuncts.add(xxYYZZ.build()); BooleanQuery.Builder xxW1 = new BooleanQuery.Builder();; xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT); xxW1.add(new TermQuery(new Term(FIELD, "w1")), Occur.MUST_NOT); - dm.add(xxW1.build()); + disjuncts.add(xxW1.build()); - DisjunctionMaxQuery dm2 = new DisjunctionMaxQuery(0.5f); - dm2.add(new TermQuery(new Term(FIELD, "w1"))); - dm2.add(new TermQuery(new Term(FIELD, "w2"))); - dm2.add(new TermQuery(new Term(FIELD, "w3"))); - dm.add(dm2); + DisjunctionMaxQuery dm2 = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term(FIELD, "w1")), + new TermQuery(new Term(FIELD, "w2")), + new TermQuery(new Term(FIELD, "w3"))), + 0.5f); + disjuncts.add(dm2); - q.add(dm, Occur.SHOULD); + q.add(new DisjunctionMaxQuery(disjuncts, 0.2f), Occur.SHOULD); BooleanQuery.Builder builder = new BooleanQuery.Builder();; builder.setMinimumNumberShouldMatch(2); @@ -211,18 +217,16 @@ public class TestComplexExplanations extends BaseExplanationTestCase { } public void testDMQ10() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder query = new BooleanQuery.Builder();; query.add(new TermQuery(new Term(FIELD, "yy")), Occur.SHOULD); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); query.add(new BoostQuery(boostedQuery, 100), Occur.SHOULD); - q.add(query.build()); - TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); - q.add(new BoostQuery(xxBoostedQuery, 0)); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(query.build(), new BoostQuery(xxBoostedQuery, 0)), + 0.5f); bqtest(new BoostQuery(q, 0), new int[] { 0,2,3 }); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java index 6b6683e8ddd..aaefa7a2172 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java @@ -20,6 +20,7 @@ package org.apache.lucene.search; import java.io.IOException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; +import java.util.Arrays; import java.util.Locale; import org.apache.lucene.analysis.Analyzer; @@ -40,7 +41,6 @@ import org.apache.lucene.index.StoredDocument; import org.apache.lucene.index.Term; import org.apache.lucene.search.similarities.ClassicSimilarity; import org.apache.lucene.search.similarities.Similarity; -import org.apache.lucene.search.spans.SpanQuery; import org.apache.lucene.search.spans.SpanTermQuery; import org.apache.lucene.store.Directory; import org.apache.lucene.util.LuceneTestCase; @@ -172,10 +172,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { } public void testSkipToFirsttimeMiss() throws IOException { - final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f); - dq.add(tq("id", "d1")); - dq.add(tq("dek", "DOES_NOT_EXIST")); - + final DisjunctionMaxQuery dq = new DisjunctionMaxQuery( + Arrays.asList(tq("id", "d1"), tq("dek", "DOES_NOT_EXIST")), 0.0f); + QueryUtils.check(random(), dq, s); assertTrue(s.getTopReaderContext() instanceof LeafReaderContext); final Weight dw = s.createNormalizedWeight(dq, true); @@ -189,9 +188,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { } public void testSkipToFirsttimeHit() throws IOException { - final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f); - dq.add(tq("dek", "albino")); - dq.add(tq("dek", "DOES_NOT_EXIST")); + final DisjunctionMaxQuery dq = new DisjunctionMaxQuery( + Arrays.asList(tq("dek", "albino"), tq("dek", "DOES_NOT_EXIST")), 0.0f); + assertTrue(s.getTopReaderContext() instanceof LeafReaderContext); QueryUtils.check(random(), dq, s); final Weight dw = s.createNormalizedWeight(dq, true); @@ -204,9 +203,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { public void testSimpleEqualScores1() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); - q.add(tq("hed", "albino")); - q.add(tq("hed", "elephant")); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "albino"), tq("hed", "elephant")), + 0.0f); QueryUtils.check(random(), q, s); ScoreDoc[] h = s.search(q, 1000).scoreDocs; @@ -228,9 +227,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { public void testSimpleEqualScores2() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); - q.add(tq("dek", "albino")); - q.add(tq("dek", "elephant")); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(tq("dek", "albino"), tq("dek", "elephant")), + 0.0f); QueryUtils.check(random(), q, s); ScoreDoc[] h = s.search(q, 1000).scoreDocs; @@ -251,11 +250,13 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { public void testSimpleEqualScores3() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); - q.add(tq("hed", "albino")); - q.add(tq("hed", "elephant")); - q.add(tq("dek", "albino")); - q.add(tq("dek", "elephant")); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + tq("hed", "albino"), + tq("hed", "elephant"), + tq("dek", "albino"), + tq("dek", "elephant")), + 0.0f); QueryUtils.check(random(), q, s); ScoreDoc[] h = s.search(q, 1000).scoreDocs; @@ -276,9 +277,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { public void testSimpleTiebreaker() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.01f); - q.add(tq("dek", "albino")); - q.add(tq("dek", "elephant")); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(tq("dek", "albino"), tq("dek", "elephant")), + 0.01f); QueryUtils.check(random(), q, s); ScoreDoc[] h = s.search(q, 1000).scoreDocs; @@ -303,17 +304,17 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { BooleanQuery.Builder q = new BooleanQuery.Builder(); { - DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f); - q1.add(tq("hed", "albino")); - q1.add(tq("dek", "albino")); + DisjunctionMaxQuery q1 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "albino"), tq("dek", "albino")), + 0.0f); q.add(q1, BooleanClause.Occur.MUST);// true,false); QueryUtils.check(random(), q1, s); } { - DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f); - q2.add(tq("hed", "elephant")); - q2.add(tq("dek", "elephant")); + DisjunctionMaxQuery q2 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")), + 0.0f); q.add(q2, BooleanClause.Occur.MUST);// true,false); QueryUtils.check(random(), q2, s); } @@ -339,15 +340,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { BooleanQuery.Builder q = new BooleanQuery.Builder(); { - DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f); - q1.add(tq("hed", "albino")); - q1.add(tq("dek", "albino")); + DisjunctionMaxQuery q1 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "albino"), tq("dek", "albino")), + 0.0f); q.add(q1, BooleanClause.Occur.SHOULD);// false,false); } { - DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f); - q2.add(tq("hed", "elephant")); - q2.add(tq("dek", "elephant")); + DisjunctionMaxQuery q2 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")), + 0.0f); q.add(q2, BooleanClause.Occur.SHOULD);// false,false); } QueryUtils.check(random(), q.build(), s); @@ -375,15 +376,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { BooleanQuery.Builder q = new BooleanQuery.Builder(); { - DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f); - q1.add(tq("hed", "albino")); - q1.add(tq("dek", "albino")); + DisjunctionMaxQuery q1 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "albino"), tq("dek", "albino")), + 0.01f); q.add(q1, BooleanClause.Occur.SHOULD);// false,false); } { - DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f); - q2.add(tq("hed", "elephant")); - q2.add(tq("dek", "elephant")); + DisjunctionMaxQuery q2 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")), + 0.01f); q.add(q2, BooleanClause.Occur.SHOULD);// false,false); } QueryUtils.check(random(), q.build(), s); @@ -429,15 +430,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { BooleanQuery.Builder q = new BooleanQuery.Builder(); { - DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f); - q1.add(tq("hed", "albino", 1.5f)); - q1.add(tq("dek", "albino")); + DisjunctionMaxQuery q1 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "albino", 1.5f), tq("dek", "albino")), + 0.01f); q.add(q1, BooleanClause.Occur.SHOULD);// false,false); } { - DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f); - q2.add(tq("hed", "elephant", 1.5f)); - q2.add(tq("dek", "elephant")); + DisjunctionMaxQuery q2 = new DisjunctionMaxQuery( + Arrays.asList(tq("hed", "elephant", 1.5f), tq("dek", "elephant")), + 0.01f); q.add(q2, BooleanClause.Occur.SHOULD);// false,false); } QueryUtils.check(random(), q.build(), s); @@ -493,11 +494,11 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase { IndexReader indexReader = DirectoryReader.open(directory); IndexSearcher searcher = newSearcher(indexReader); - DisjunctionMaxQuery query = new DisjunctionMaxQuery(1.0f); - SpanQuery sq1 = new SpanTermQuery(new Term(FIELD, "clockwork")); - SpanQuery sq2 = new SpanTermQuery(new Term(FIELD, "clckwork")); - query.add(sq1); - query.add(sq2); + DisjunctionMaxQuery query = new DisjunctionMaxQuery( + Arrays.asList( + new SpanTermQuery(new Term(FIELD, "clockwork")), + new SpanTermQuery(new Term(FIELD, "clckwork"))), + 1.0f); TopScoreDocCollector collector = TopScoreDocCollector.create(1000); searcher.search(query, collector); hits = collector.topDocs().scoreDocs.length; diff --git a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java index c41f7edd2cb..89d53c27a8a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestLRUQueryCache.java @@ -19,6 +19,7 @@ package org.apache.lucene.search; import java.io.IOException; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -861,12 +862,12 @@ public class TestLRUQueryCache extends LuceneTestCase { case 4: return new ConstantScoreQuery(buildRandomQuery(level + 1)); case 5: - DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(random().nextFloat()); + List disjuncts = new ArrayList<>(); final int numQueries = TestUtil.nextInt(random(), 1, 3); for (int i = 0; i < numQueries; ++i) { - dmq.add(buildRandomQuery(level + 1)); + disjuncts.add(buildRandomQuery(level + 1)); } - return dmq; + return new DisjunctionMaxQuery(disjuncts, random().nextFloat()); default: throw new AssertionError(); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java b/lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java index 92702aade22..6d862d8ad08 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSimpleExplanations.java @@ -17,6 +17,8 @@ package org.apache.lucene.search; * limitations under the License. */ +import java.util.Arrays; + import org.apache.lucene.index.Term; /** @@ -98,89 +100,99 @@ public class TestSimpleExplanations extends BaseExplanationTestCase { /* DisjunctionMaxQuery */ public void testDMQ1() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); - q.add(new TermQuery(new Term(FIELD, "w1"))); - q.add(new TermQuery(new Term(FIELD, "w5"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term(FIELD, "w1")), + new TermQuery(new Term(FIELD, "w5"))), + 0.0f); qtest(q, new int[] { 0,1,2,3 }); } public void testDMQ2() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - q.add(new TermQuery(new Term(FIELD, "w1"))); - q.add(new TermQuery(new Term(FIELD, "w5"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term(FIELD, "w1")), + new TermQuery(new Term(FIELD, "w5"))), + 0.5f); qtest(q, new int[] { 0,1,2,3 }); } public void testDMQ3() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - q.add(new TermQuery(new Term(FIELD, "QQ"))); - q.add(new TermQuery(new Term(FIELD, "w5"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term(FIELD, "QQ")), + new TermQuery(new Term(FIELD, "w5"))), + 0.5f); qtest(q, new int[] { 0 }); } public void testDMQ4() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - q.add(new TermQuery(new Term(FIELD, "QQ"))); - q.add(new TermQuery(new Term(FIELD, "xx"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term(FIELD, "QQ")), + new TermQuery(new Term(FIELD, "xx"))), + 0.5f); qtest(q, new int[] { 2,3 }); } public void testDMQ5() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "QQ")), BooleanClause.Occur.MUST_NOT); - q.add(booleanQuery.build()); - q.add(new TermQuery(new Term(FIELD, "xx"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + booleanQuery.build(), + new TermQuery(new Term(FIELD, "xx"))), + 0.5f); qtest(q, new int[] { 2,3 }); } public void testDMQ6() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.MUST_NOT); booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD); - q.add(booleanQuery.build()); - q.add(new TermQuery(new Term(FIELD, "xx"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + booleanQuery.build(), + new TermQuery(new Term(FIELD, "xx"))), + 0.5f); qtest(q, new int[] { 0,1,2,3 }); } public void testDMQ7() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.MUST_NOT); booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD); - q.add(booleanQuery.build()); - q.add(new TermQuery(new Term(FIELD, "w2"))); + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList( + booleanQuery.build(), + new TermQuery(new Term(FIELD, "w2"))), + 0.5f); qtest(q, new int[] { 0,1,2,3 }); } public void testDMQ8() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD); - q.add(booleanQuery.build()); TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); - q.add(new BoostQuery(xxBoostedQuery, 100000)); - + + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(booleanQuery.build(), new BoostQuery(xxBoostedQuery, 100000)), + 0.5f); qtest(q, new int[] { 0,2,3 }); } public void testDMQ9() throws Exception { - DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); - BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD); - q.add(booleanQuery.build()); TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); - q.add(new BoostQuery(xxBoostedQuery, 0)); + + DisjunctionMaxQuery q = new DisjunctionMaxQuery( + Arrays.asList(booleanQuery.build(), new BoostQuery(xxBoostedQuery, 0)), + 0.5f); qtest(q, new int[] { 0,2,3 }); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java b/lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java index 978949e6fb6..d67fb95031b 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestSimpleSearchEquivalence.java @@ -1,5 +1,7 @@ package org.apache.lucene.search; +import java.util.Arrays; + import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause.Occur; @@ -82,9 +84,11 @@ public class TestSimpleSearchEquivalence extends SearchEquivalenceTestBase { BooleanQuery.Builder q1 = new BooleanQuery.Builder(); q1.add(new TermQuery(t1), Occur.SHOULD); q1.add(new TermQuery(t2), Occur.SHOULD); - DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.5f); - q2.add(new TermQuery(t1)); - q2.add(new TermQuery(t2)); + DisjunctionMaxQuery q2 = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(t1), + new TermQuery(t2)), + 0.5f); assertSameSet(q1.build(), q2); } diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java index 5e45d22fc6e..85a1f0365b8 100644 --- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java +++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java @@ -18,8 +18,10 @@ package org.apache.lucene.search.highlight; */ import java.io.IOException; +import java.util.Arrays; import com.carrotsearch.randomizedtesting.annotations.Repeat; + import org.apache.lucene.analysis.BaseTokenStreamTestCase; import org.apache.lucene.analysis.CannedTokenStream; import org.apache.lucene.analysis.MockAnalyzer; @@ -118,9 +120,11 @@ public class TokenSourcesTest extends BaseTokenStreamTestCase { assertEquals(1, indexReader.numDocs()); final IndexSearcher indexSearcher = newSearcher(indexReader); try { - final DisjunctionMaxQuery query = new DisjunctionMaxQuery(1); - query.add(new SpanTermQuery(new Term(FIELD, "{fox}"))); - query.add(new SpanTermQuery(new Term(FIELD, "fox"))); + final DisjunctionMaxQuery query = new DisjunctionMaxQuery( + Arrays.asList( + new SpanTermQuery(new Term(FIELD, "{fox}")), + new SpanTermQuery(new Term(FIELD, "fox"))), + 1); // final Query phraseQuery = new SpanNearQuery(new SpanQuery[] { // new SpanTermQuery(new Term(FIELD, "{fox}")), // new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true); @@ -161,9 +165,11 @@ public class TokenSourcesTest extends BaseTokenStreamTestCase { try { assertEquals(1, indexReader.numDocs()); final IndexSearcher indexSearcher = newSearcher(indexReader); - final DisjunctionMaxQuery query = new DisjunctionMaxQuery(1); - query.add(new SpanTermQuery(new Term(FIELD, "{fox}"))); - query.add(new SpanTermQuery(new Term(FIELD, "fox"))); + final DisjunctionMaxQuery query = new DisjunctionMaxQuery( + Arrays.asList( + new SpanTermQuery(new Term(FIELD, "{fox}")), + new SpanTermQuery(new Term(FIELD, "fox"))), + 1); // final Query phraseQuery = new SpanNearQuery(new SpanQuery[] { // new SpanTermQuery(new Term(FIELD, "{fox}")), // new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true); diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestMultiTermHighlighting.java b/lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestMultiTermHighlighting.java index 9369b7bac7f..99ef2372406 100644 --- a/lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestMultiTermHighlighting.java +++ b/lucene/highlighter/src/test/org/apache/lucene/search/postingshighlight/TestMultiTermHighlighting.java @@ -17,6 +17,8 @@ package org.apache.lucene.search.postingshighlight; * limitations under the License. */ +import java.util.Collections; + import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.analysis.MockTokenizer; @@ -555,8 +557,8 @@ public class TestMultiTermHighlighting extends LuceneTestCase { return analyzer; } }; - DisjunctionMaxQuery query = new DisjunctionMaxQuery(0); - query.add(new WildcardQuery(new Term("body", "te*"))); + DisjunctionMaxQuery query = new DisjunctionMaxQuery( + Collections.singleton(new WildcardQuery(new Term("body", "te*"))), 0); TopDocs topDocs = searcher.search(query, 10, Sort.INDEXORDER); assertEquals(2, topDocs.totalHits); String snippets[] = highlighter.highlight("body", query, searcher, topDocs); diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java index 67f0ab62f24..0cc975e6a1c 100644 --- a/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java +++ b/lucene/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java @@ -19,6 +19,7 @@ package org.apache.lucene.search.vectorhighlight; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -153,11 +154,7 @@ public abstract class AbstractTestCase extends LuceneTestCase { } protected Query dmq( float tieBreakerMultiplier, Query... queries ){ - DisjunctionMaxQuery query = new DisjunctionMaxQuery( tieBreakerMultiplier ); - for( Query q : queries ){ - query.add( q ); - } - return query; + return new DisjunctionMaxQuery(Arrays.asList(queries), tieBreakerMultiplier); } protected void assertCollectionQueries( Collection actual, Query... expected ){ diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/DisjunctionMaxQueryBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/DisjunctionMaxQueryBuilder.java index 48944f8c5a4..70bdc98baa7 100644 --- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/DisjunctionMaxQueryBuilder.java +++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/xml/builders/DisjunctionMaxQueryBuilder.java @@ -16,6 +16,9 @@ package org.apache.lucene.queryparser.xml.builders; * limitations under the License. */ +import java.util.ArrayList; +import java.util.List; + import org.apache.lucene.queryparser.xml.DOMUtils; import org.apache.lucene.queryparser.xml.ParserException; import org.apache.lucene.queryparser.xml.QueryBuilder; @@ -44,22 +47,22 @@ public class DisjunctionMaxQueryBuilder implements QueryBuilder { @Override public Query getQuery(Element e) throws ParserException { float tieBreaker = DOMUtils.getAttribute(e, "tieBreaker", 0.0f); - DisjunctionMaxQuery dq = new DisjunctionMaxQuery(tieBreaker); + List disjuncts = new ArrayList<>(); NodeList nl = e.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { // all elements are disjuncts. Element queryElem = (Element) node; Query q = factory.getQuery(queryElem); - dq.add(q); + disjuncts.add(q); } } - Query q = dq; + Query q = new DisjunctionMaxQuery(disjuncts, tieBreaker); float boost = DOMUtils.getAttribute(e, "boost", 1.0f); if (boost != 1f) { - q = new BoostQuery(dq, boost); + q = new BoostQuery(q, boost); } return q; } diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java index e8acc74f972..2e3fdc35b9e 100644 --- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java +++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java @@ -865,13 +865,8 @@ public class SolrPluginUtils { if (aliases.containsKey(field)) { Alias a = aliases.get(field); - DisjunctionMaxQuery q = new DisjunctionMaxQuery(a.tie); - - /* we might not get any valid queries from delegation, - * in which case we should return null - */ - boolean ok = false; + List disjuncts = new ArrayList<>(); for (String f : a.fields.keySet()) { Query sub = getFieldQuery(f,queryText,quoted); @@ -879,11 +874,12 @@ public class SolrPluginUtils { if (null != a.fields.get(f)) { sub = new BoostQuery(sub, a.fields.get(f)); } - q.add(sub); - ok = true; + disjuncts.add(sub); } } - return ok ? q : null; + return disjuncts.isEmpty() + ? null + : new DisjunctionMaxQuery(disjuncts, a.tie); } else { try { diff --git a/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java index 862a86404e8..d82b2c5e069 100644 --- a/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java +++ b/solr/core/src/test/org/apache/solr/search/TestMaxScoreQueryParser.java @@ -21,7 +21,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.*; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.util.AbstractSolrTestCase; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -72,7 +71,7 @@ public class TestMaxScoreQueryParser extends AbstractSolrTestCase { assertEquals(1, clauses.length); assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery); assertEquals(0.0, ((DisjunctionMaxQuery) clauses[0].getQuery()).getTieBreakerMultiplier(), 1e-15); - ArrayList qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts(); + List qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts(); assertEquals(2, qa.size()); assertEquals("text:foo", qa.get(0).toString()); } diff --git a/solr/core/src/test/org/apache/solr/util/SolrPluginUtilsTest.java b/solr/core/src/test/org/apache/solr/util/SolrPluginUtilsTest.java index ecc804ec36e..82e4862d018 100644 --- a/solr/core/src/test/org/apache/solr/util/SolrPluginUtilsTest.java +++ b/solr/core/src/test/org/apache/solr/util/SolrPluginUtilsTest.java @@ -38,6 +38,8 @@ import org.junit.BeforeClass; import org.junit.Test; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -419,16 +421,18 @@ public class SolrPluginUtilsTest extends SolrTestCaseJ4 { /* Simulate stopwords through uneven disjuncts */ q = new BooleanQuery.Builder(); - DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(0.0f); - dmq.add(new TermQuery(new Term("a","foo"))); + q.add(new DisjunctionMaxQuery(Collections.singleton(new TermQuery(new Term("a","foo"))), 0.0f), Occur.SHOULD); + DisjunctionMaxQuery dmq = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term("a","foo")), + new TermQuery(new Term("b","foo"))), + 0f); q.add(dmq, Occur.SHOULD); - dmq = new DisjunctionMaxQuery(0.0f); - dmq.add(new TermQuery(new Term("a","foo"))); - dmq.add(new TermQuery(new Term("b","foo"))); - q.add(dmq, Occur.SHOULD); - dmq = new DisjunctionMaxQuery(0.0f); - dmq.add(new TermQuery(new Term("a","bar"))); - dmq.add(new TermQuery(new Term("b","bar"))); + dmq = new DisjunctionMaxQuery( + Arrays.asList( + new TermQuery(new Term("a","bar")), + new TermQuery(new Term("b","bar"))), + 0f); q.add(dmq, Occur.SHOULD); // Without relax