LUCENE-6870: Make DisjunctionMaxQuery immutable.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1711509 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Adrien Grand 2015-10-30 17:12:38 +00:00
parent dc66518401
commit ae779d8115
15 changed files with 214 additions and 202 deletions

View File

@ -135,6 +135,9 @@ API Changes
* LUCENE-6855: CachingWrapperQuery is deprecated and will be removed in 6.0. * LUCENE-6855: CachingWrapperQuery is deprecated and will be removed in 6.0.
(Adrien Grand) (Adrien Grand)
* LUCENE-6870: DisjunctionMaxQuery#add is now deprecated, clauses should all be
provided at construction time. (Adrien Grand)
Optimizations Optimizations
* LUCENE-6708: TopFieldCollector does not compute the score several times on the * LUCENE-6708: TopFieldCollector does not compute the score several times on the

View File

@ -18,7 +18,9 @@ package org.apache.lucene.search;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -45,58 +47,36 @@ import org.apache.lucene.index.Term;
public final class DisjunctionMaxQuery extends Query implements Iterable<Query> { public final class DisjunctionMaxQuery extends Query implements Iterable<Query> {
/* The subqueries */ /* The subqueries */
private ArrayList<Query> 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. */ /* Multiple of the non-max disjunct scores added into our final score. Non-zero values support tie-breaking. */
private float tieBreakerMultiplier = 0.0f; private final float tieBreakerMultiplier;
/** 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;
}
/** /**
* Creates a new DisjunctionMaxQuery * Creates a new DisjunctionMaxQuery
* @param disjuncts a {@code Collection<Query>} of all the disjuncts to add * @param disjuncts a {@code Collection<Query>} 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<Query> disjuncts, float tieBreakerMultiplier) { public DisjunctionMaxQuery(Collection<Query> disjuncts, float tieBreakerMultiplier) {
Objects.requireNonNull(disjuncts, "Collection of Querys must not be null"); Objects.requireNonNull(disjuncts, "Collection of Querys must not be null");
this.tieBreakerMultiplier = tieBreakerMultiplier; this.tieBreakerMultiplier = tieBreakerMultiplier;
add(disjuncts); this.disjuncts = disjuncts.toArray(new Query[disjuncts.size()]);
}
/** 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<Query>}
* @param disjuncts a collection of queries to add as disjuncts.
*/
public void add(Collection<Query> disjuncts) {
this.disjuncts.addAll(Objects.requireNonNull(disjuncts, "Query connection must not be null"));
} }
/** @return An {@code Iterator<Query>} over the disjuncts */ /** @return An {@code Iterator<Query>} over the disjuncts */
@Override @Override
public Iterator<Query> iterator() { public Iterator<Query> iterator() {
return disjuncts.iterator(); return getDisjuncts().iterator();
} }
/** /**
* @return the disjuncts. * @return the disjuncts.
*/ */
public ArrayList<Query> getDisjuncts() { public List<Query> getDisjuncts() {
return disjuncts; return Collections.unmodifiableList(Arrays.asList(disjuncts));
} }
/** /**
@ -215,21 +195,22 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
* @return an optimized copy of us (which may not be a copy if there is nothing to optimize) */ * @return an optimized copy of us (which may not be a copy if there is nothing to optimize) */
@Override @Override
public Query rewrite(IndexReader reader) throws IOException { public Query rewrite(IndexReader reader) throws IOException {
int numDisjunctions = disjuncts.size(); if (disjuncts.length == 1) {
if (numDisjunctions == 1) { return disjuncts[0];
return disjuncts.get(0);
} }
DisjunctionMaxQuery rewritten = new DisjunctionMaxQuery(tieBreakerMultiplier);
boolean actuallyRewritten = false; boolean actuallyRewritten = false;
List<Query> rewrittenDisjuncts = new ArrayList<>();
for (Query sub : disjuncts) { for (Query sub : disjuncts) {
Query rewrittenSub = sub.rewrite(reader); Query rewrittenSub = sub.rewrite(reader);
actuallyRewritten |= rewrittenSub != sub; actuallyRewritten |= rewrittenSub != sub;
rewritten.add(rewrittenSub); rewrittenDisjuncts.add(rewrittenSub);
} }
if (actuallyRewritten) { if (actuallyRewritten) {
return rewritten; return new DisjunctionMaxQuery(rewrittenDisjuncts, tieBreakerMultiplier);
} }
return super.rewrite(reader); return super.rewrite(reader);
} }
@ -241,16 +222,15 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
public String toString(String field) { public String toString(String field) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
buffer.append("("); buffer.append("(");
int numDisjunctions = disjuncts.size(); for (int i = 0 ; i < disjuncts.length; i++) {
for (int i = 0 ; i < numDisjunctions; i++) { Query subquery = disjuncts[i];
Query subquery = disjuncts.get(i);
if (subquery instanceof BooleanQuery) { // wrap sub-bools in parens if (subquery instanceof BooleanQuery) { // wrap sub-bools in parens
buffer.append("("); buffer.append("(");
buffer.append(subquery.toString(field)); buffer.append(subquery.toString(field));
buffer.append(")"); buffer.append(")");
} }
else buffer.append(subquery.toString(field)); else buffer.append(subquery.toString(field));
if (i != numDisjunctions-1) buffer.append(" | "); if (i != disjuncts.length-1) buffer.append(" | ");
} }
buffer.append(")"); buffer.append(")");
if (tieBreakerMultiplier != 0.0f) { if (tieBreakerMultiplier != 0.0f) {
@ -270,7 +250,7 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
DisjunctionMaxQuery other = (DisjunctionMaxQuery)o; DisjunctionMaxQuery other = (DisjunctionMaxQuery)o;
return super.equals(o) return super.equals(o)
&& this.tieBreakerMultiplier == other.tieBreakerMultiplier && this.tieBreakerMultiplier == other.tieBreakerMultiplier
&& this.disjuncts.equals(other.disjuncts); && Arrays.equals(disjuncts, other.disjuncts);
} }
/** Compute a hash code for hashing us /** Compute a hash code for hashing us
@ -280,7 +260,7 @@ public final class DisjunctionMaxQuery extends Query implements Iterable<Query>
public int hashCode() { public int hashCode() {
int h = super.hashCode(); int h = super.hashCode();
h = 31 * h + Float.floatToIntBits(tieBreakerMultiplier); h = 31 * h + Float.floatToIntBits(tieBreakerMultiplier);
h = 31 * h + disjuncts.hashCode(); h = 31 * h + Arrays.hashCode(disjuncts);
return h; return h;
} }

View File

@ -250,9 +250,9 @@ public class TestBooleanQuery extends LuceneTestCase {
q.add(pq, BooleanClause.Occur.MUST); q.add(pq, BooleanClause.Occur.MUST);
assertEquals(0, s.search(q.build(), 10).totalHits); assertEquals(0, s.search(q.build(), 10).totalHits);
DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(1.0f); DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(
dmq.add(new TermQuery(new Term("field", "a"))); Arrays.asList(new TermQuery(new Term("field", "a")), pq),
dmq.add(pq); 1.0f);
assertEquals(1, s.search(dmq, 10).totalHits); assertEquals(1, s.search(dmq, 10).totalHits);
r.close(); r.close();

View File

@ -17,6 +17,10 @@ package org.apache.lucene.search;
* limitations under the License. * 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.index.Term;
import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.similarities.ClassicSimilarity; import org.apache.lucene.search.similarities.ClassicSimilarity;
@ -77,33 +81,33 @@ public class TestComplexExplanations extends BaseExplanationTestCase {
t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2})); t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2}));
q.add(new BoostQuery(t, 30), Occur.SHOULD); q.add(new BoostQuery(t, 30), Occur.SHOULD);
DisjunctionMaxQuery dm = new DisjunctionMaxQuery(0.2f); List<Query> disjuncts = new ArrayList<>();
dm.add(snear(st("w2"), disjuncts.add(snear(st("w2"),
sor("w5","zz"), sor("w5","zz"),
4, true)); 4, true));
dm.add(new TermQuery(new Term(FIELD, "QQ"))); disjuncts.add(new TermQuery(new Term(FIELD, "QQ")));
BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();; BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();;
xxYYZZ.add(new TermQuery(new Term(FIELD, "xx")), Occur.SHOULD); 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, "yy")), Occur.SHOULD);
xxYYZZ.add(new TermQuery(new Term(FIELD, "zz")), Occur.MUST_NOT); 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();; BooleanQuery.Builder xxW1 = new BooleanQuery.Builder();;
xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT); xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT);
xxW1.add(new TermQuery(new Term(FIELD, "w1")), 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); List<Query> disjuncts2 = new ArrayList<>();
dm2.add(new TermQuery(new Term(FIELD, "w1"))); disjuncts2.add(new TermQuery(new Term(FIELD, "w1")));
dm2.add(new TermQuery(new Term(FIELD, "w2"))); disjuncts2.add(new TermQuery(new Term(FIELD, "w2")));
dm2.add(new TermQuery(new Term(FIELD, "w3"))); disjuncts2.add(new TermQuery(new Term(FIELD, "w3")));
dm.add(dm2); 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();; BooleanQuery.Builder b = new BooleanQuery.Builder();;
b.setMinimumNumberShouldMatch(2); b.setMinimumNumberShouldMatch(2);
@ -138,32 +142,34 @@ public class TestComplexExplanations extends BaseExplanationTestCase {
t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2})); t = new ConstantScoreQuery(matchTheseItems(new int[] {0,2}));
q.add(new BoostQuery(t, -20), Occur.SHOULD); q.add(new BoostQuery(t, -20), Occur.SHOULD);
DisjunctionMaxQuery dm = new DisjunctionMaxQuery(0.2f); List<Query> disjuncts = new ArrayList<>();
dm.add(snear(st("w2"), disjuncts.add(snear(st("w2"),
sor("w5","zz"), sor("w5","zz"),
4, true)); 4, true));
dm.add(new TermQuery(new Term(FIELD, "QQ"))); disjuncts.add(new TermQuery(new Term(FIELD, "QQ")));
BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();; BooleanQuery.Builder xxYYZZ = new BooleanQuery.Builder();;
xxYYZZ.add(new TermQuery(new Term(FIELD, "xx")), Occur.SHOULD); 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, "yy")), Occur.SHOULD);
xxYYZZ.add(new TermQuery(new Term(FIELD, "zz")), Occur.MUST_NOT); 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();; BooleanQuery.Builder xxW1 = new BooleanQuery.Builder();;
xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT); xxW1.add(new TermQuery(new Term(FIELD, "xx")), Occur.MUST_NOT);
xxW1.add(new TermQuery(new Term(FIELD, "w1")), 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); DisjunctionMaxQuery dm2 = new DisjunctionMaxQuery(
dm2.add(new TermQuery(new Term(FIELD, "w1"))); Arrays.asList(
dm2.add(new TermQuery(new Term(FIELD, "w2"))); new TermQuery(new Term(FIELD, "w1")),
dm2.add(new TermQuery(new Term(FIELD, "w3"))); new TermQuery(new Term(FIELD, "w2")),
dm.add(dm2); 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();; BooleanQuery.Builder builder = new BooleanQuery.Builder();;
builder.setMinimumNumberShouldMatch(2); builder.setMinimumNumberShouldMatch(2);
@ -211,18 +217,16 @@ public class TestComplexExplanations extends BaseExplanationTestCase {
} }
public void testDMQ10() throws Exception { public void testDMQ10() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder query = new BooleanQuery.Builder();; BooleanQuery.Builder query = new BooleanQuery.Builder();;
query.add(new TermQuery(new Term(FIELD, "yy")), Occur.SHOULD); query.add(new TermQuery(new Term(FIELD, "yy")), Occur.SHOULD);
TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5"));
query.add(new BoostQuery(boostedQuery, 100), Occur.SHOULD); query.add(new BoostQuery(boostedQuery, 100), Occur.SHOULD);
q.add(query.build());
TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); 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 }); bqtest(new BoostQuery(q, 0), new int[] { 0,2,3 });
} }

View File

@ -20,6 +20,7 @@ package org.apache.lucene.search;
import java.io.IOException; import java.io.IOException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import org.apache.lucene.analysis.Analyzer; 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.index.Term;
import org.apache.lucene.search.similarities.ClassicSimilarity; import org.apache.lucene.search.similarities.ClassicSimilarity;
import org.apache.lucene.search.similarities.Similarity; 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.search.spans.SpanTermQuery;
import org.apache.lucene.store.Directory; import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
@ -172,10 +172,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
} }
public void testSkipToFirsttimeMiss() throws IOException { public void testSkipToFirsttimeMiss() throws IOException {
final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f); final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(
dq.add(tq("id", "d1")); Arrays.asList(tq("id", "d1"), tq("dek", "DOES_NOT_EXIST")), 0.0f);
dq.add(tq("dek", "DOES_NOT_EXIST"));
QueryUtils.check(random(), dq, s); QueryUtils.check(random(), dq, s);
assertTrue(s.getTopReaderContext() instanceof LeafReaderContext); assertTrue(s.getTopReaderContext() instanceof LeafReaderContext);
final Weight dw = s.createNormalizedWeight(dq, true); final Weight dw = s.createNormalizedWeight(dq, true);
@ -189,9 +188,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
} }
public void testSkipToFirsttimeHit() throws IOException { public void testSkipToFirsttimeHit() throws IOException {
final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(0.0f); final DisjunctionMaxQuery dq = new DisjunctionMaxQuery(
dq.add(tq("dek", "albino")); Arrays.asList(tq("dek", "albino"), tq("dek", "DOES_NOT_EXIST")), 0.0f);
dq.add(tq("dek", "DOES_NOT_EXIST"));
assertTrue(s.getTopReaderContext() instanceof LeafReaderContext); assertTrue(s.getTopReaderContext() instanceof LeafReaderContext);
QueryUtils.check(random(), dq, s); QueryUtils.check(random(), dq, s);
final Weight dw = s.createNormalizedWeight(dq, true); final Weight dw = s.createNormalizedWeight(dq, true);
@ -204,9 +203,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
public void testSimpleEqualScores1() throws Exception { public void testSimpleEqualScores1() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(tq("hed", "albino")); Arrays.asList(tq("hed", "albino"), tq("hed", "elephant")),
q.add(tq("hed", "elephant")); 0.0f);
QueryUtils.check(random(), q, s); QueryUtils.check(random(), q, s);
ScoreDoc[] h = s.search(q, 1000).scoreDocs; ScoreDoc[] h = s.search(q, 1000).scoreDocs;
@ -228,9 +227,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
public void testSimpleEqualScores2() throws Exception { public void testSimpleEqualScores2() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(tq("dek", "albino")); Arrays.asList(tq("dek", "albino"), tq("dek", "elephant")),
q.add(tq("dek", "elephant")); 0.0f);
QueryUtils.check(random(), q, s); QueryUtils.check(random(), q, s);
ScoreDoc[] h = s.search(q, 1000).scoreDocs; ScoreDoc[] h = s.search(q, 1000).scoreDocs;
@ -251,11 +250,13 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
public void testSimpleEqualScores3() throws Exception { public void testSimpleEqualScores3() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(tq("hed", "albino")); Arrays.asList(
q.add(tq("hed", "elephant")); tq("hed", "albino"),
q.add(tq("dek", "albino")); tq("hed", "elephant"),
q.add(tq("dek", "elephant")); tq("dek", "albino"),
tq("dek", "elephant")),
0.0f);
QueryUtils.check(random(), q, s); QueryUtils.check(random(), q, s);
ScoreDoc[] h = s.search(q, 1000).scoreDocs; ScoreDoc[] h = s.search(q, 1000).scoreDocs;
@ -276,9 +277,9 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
public void testSimpleTiebreaker() throws Exception { public void testSimpleTiebreaker() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.01f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(tq("dek", "albino")); Arrays.asList(tq("dek", "albino"), tq("dek", "elephant")),
q.add(tq("dek", "elephant")); 0.01f);
QueryUtils.check(random(), q, s); QueryUtils.check(random(), q, s);
ScoreDoc[] h = s.search(q, 1000).scoreDocs; ScoreDoc[] h = s.search(q, 1000).scoreDocs;
@ -303,17 +304,17 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
BooleanQuery.Builder q = new BooleanQuery.Builder(); BooleanQuery.Builder q = new BooleanQuery.Builder();
{ {
DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(
q1.add(tq("hed", "albino")); Arrays.asList(tq("hed", "albino"), tq("dek", "albino")),
q1.add(tq("dek", "albino")); 0.0f);
q.add(q1, BooleanClause.Occur.MUST);// true,false); q.add(q1, BooleanClause.Occur.MUST);// true,false);
QueryUtils.check(random(), q1, s); QueryUtils.check(random(), q1, s);
} }
{ {
DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(
q2.add(tq("hed", "elephant")); Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")),
q2.add(tq("dek", "elephant")); 0.0f);
q.add(q2, BooleanClause.Occur.MUST);// true,false); q.add(q2, BooleanClause.Occur.MUST);// true,false);
QueryUtils.check(random(), q2, s); QueryUtils.check(random(), q2, s);
} }
@ -339,15 +340,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
BooleanQuery.Builder q = new BooleanQuery.Builder(); BooleanQuery.Builder q = new BooleanQuery.Builder();
{ {
DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(
q1.add(tq("hed", "albino")); Arrays.asList(tq("hed", "albino"), tq("dek", "albino")),
q1.add(tq("dek", "albino")); 0.0f);
q.add(q1, BooleanClause.Occur.SHOULD);// false,false); q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
} }
{ {
DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(
q2.add(tq("hed", "elephant")); Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")),
q2.add(tq("dek", "elephant")); 0.0f);
q.add(q2, BooleanClause.Occur.SHOULD);// false,false); q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
} }
QueryUtils.check(random(), q.build(), s); QueryUtils.check(random(), q.build(), s);
@ -375,15 +376,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
BooleanQuery.Builder q = new BooleanQuery.Builder(); BooleanQuery.Builder q = new BooleanQuery.Builder();
{ {
DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f); DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(
q1.add(tq("hed", "albino")); Arrays.asList(tq("hed", "albino"), tq("dek", "albino")),
q1.add(tq("dek", "albino")); 0.01f);
q.add(q1, BooleanClause.Occur.SHOULD);// false,false); q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
} }
{ {
DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f); DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(
q2.add(tq("hed", "elephant")); Arrays.asList(tq("hed", "elephant"), tq("dek", "elephant")),
q2.add(tq("dek", "elephant")); 0.01f);
q.add(q2, BooleanClause.Occur.SHOULD);// false,false); q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
} }
QueryUtils.check(random(), q.build(), s); QueryUtils.check(random(), q.build(), s);
@ -429,15 +430,15 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
BooleanQuery.Builder q = new BooleanQuery.Builder(); BooleanQuery.Builder q = new BooleanQuery.Builder();
{ {
DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(0.01f); DisjunctionMaxQuery q1 = new DisjunctionMaxQuery(
q1.add(tq("hed", "albino", 1.5f)); Arrays.asList(tq("hed", "albino", 1.5f), tq("dek", "albino")),
q1.add(tq("dek", "albino")); 0.01f);
q.add(q1, BooleanClause.Occur.SHOULD);// false,false); q.add(q1, BooleanClause.Occur.SHOULD);// false,false);
} }
{ {
DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.01f); DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(
q2.add(tq("hed", "elephant", 1.5f)); Arrays.asList(tq("hed", "elephant", 1.5f), tq("dek", "elephant")),
q2.add(tq("dek", "elephant")); 0.01f);
q.add(q2, BooleanClause.Occur.SHOULD);// false,false); q.add(q2, BooleanClause.Occur.SHOULD);// false,false);
} }
QueryUtils.check(random(), q.build(), s); QueryUtils.check(random(), q.build(), s);
@ -493,11 +494,11 @@ public class TestDisjunctionMaxQuery extends LuceneTestCase {
IndexReader indexReader = DirectoryReader.open(directory); IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher searcher = newSearcher(indexReader); IndexSearcher searcher = newSearcher(indexReader);
DisjunctionMaxQuery query = new DisjunctionMaxQuery(1.0f); DisjunctionMaxQuery query = new DisjunctionMaxQuery(
SpanQuery sq1 = new SpanTermQuery(new Term(FIELD, "clockwork")); Arrays.asList(
SpanQuery sq2 = new SpanTermQuery(new Term(FIELD, "clckwork")); new SpanTermQuery(new Term(FIELD, "clockwork")),
query.add(sq1); new SpanTermQuery(new Term(FIELD, "clckwork"))),
query.add(sq2); 1.0f);
TopScoreDocCollector collector = TopScoreDocCollector.create(1000); TopScoreDocCollector collector = TopScoreDocCollector.create(1000);
searcher.search(query, collector); searcher.search(query, collector);
hits = collector.topDocs().scoreDocs.length; hits = collector.topDocs().scoreDocs.length;

View File

@ -19,6 +19,7 @@ package org.apache.lucene.search;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -861,12 +862,12 @@ public class TestLRUQueryCache extends LuceneTestCase {
case 4: case 4:
return new ConstantScoreQuery(buildRandomQuery(level + 1)); return new ConstantScoreQuery(buildRandomQuery(level + 1));
case 5: case 5:
DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(random().nextFloat()); List<Query> disjuncts = new ArrayList<>();
final int numQueries = TestUtil.nextInt(random(), 1, 3); final int numQueries = TestUtil.nextInt(random(), 1, 3);
for (int i = 0; i < numQueries; ++i) { 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: default:
throw new AssertionError(); throw new AssertionError();
} }

View File

@ -17,6 +17,8 @@ package org.apache.lucene.search;
* limitations under the License. * limitations under the License.
*/ */
import java.util.Arrays;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
/** /**
@ -98,89 +100,99 @@ public class TestSimpleExplanations extends BaseExplanationTestCase {
/* DisjunctionMaxQuery */ /* DisjunctionMaxQuery */
public void testDMQ1() throws Exception { public void testDMQ1() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.0f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "w1"))); Arrays.asList(
q.add(new TermQuery(new Term(FIELD, "w5"))); new TermQuery(new Term(FIELD, "w1")),
new TermQuery(new Term(FIELD, "w5"))),
0.0f);
qtest(q, new int[] { 0,1,2,3 }); qtest(q, new int[] { 0,1,2,3 });
} }
public void testDMQ2() throws Exception { public void testDMQ2() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "w1"))); Arrays.asList(
q.add(new TermQuery(new Term(FIELD, "w5"))); new TermQuery(new Term(FIELD, "w1")),
new TermQuery(new Term(FIELD, "w5"))),
0.5f);
qtest(q, new int[] { 0,1,2,3 }); qtest(q, new int[] { 0,1,2,3 });
} }
public void testDMQ3() throws Exception { public void testDMQ3() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "QQ"))); Arrays.asList(
q.add(new TermQuery(new Term(FIELD, "w5"))); new TermQuery(new Term(FIELD, "QQ")),
new TermQuery(new Term(FIELD, "w5"))),
0.5f);
qtest(q, new int[] { 0 }); qtest(q, new int[] { 0 });
} }
public void testDMQ4() throws Exception { public void testDMQ4() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "QQ"))); Arrays.asList(
q.add(new TermQuery(new Term(FIELD, "xx"))); new TermQuery(new Term(FIELD, "QQ")),
new TermQuery(new Term(FIELD, "xx"))),
0.5f);
qtest(q, new int[] { 2,3 }); qtest(q, new int[] { 2,3 });
} }
public void testDMQ5() throws Exception { public void testDMQ5() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD);
booleanQuery.add(new TermQuery(new Term(FIELD, "QQ")), BooleanClause.Occur.MUST_NOT); booleanQuery.add(new TermQuery(new Term(FIELD, "QQ")), BooleanClause.Occur.MUST_NOT);
q.add(booleanQuery.build()); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "xx"))); Arrays.asList(
booleanQuery.build(),
new TermQuery(new Term(FIELD, "xx"))),
0.5f);
qtest(q, new int[] { 2,3 }); qtest(q, new int[] { 2,3 });
} }
public void testDMQ6() throws Exception { public void testDMQ6() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); 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, "yy")), BooleanClause.Occur.MUST_NOT);
booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD);
q.add(booleanQuery.build()); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "xx"))); Arrays.asList(
booleanQuery.build(),
new TermQuery(new Term(FIELD, "xx"))),
0.5f);
qtest(q, new int[] { 0,1,2,3 }); qtest(q, new int[] { 0,1,2,3 });
} }
public void testDMQ7() throws Exception { public void testDMQ7() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); 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, "yy")), BooleanClause.Occur.MUST_NOT);
booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "w3")), BooleanClause.Occur.SHOULD);
q.add(booleanQuery.build()); DisjunctionMaxQuery q = new DisjunctionMaxQuery(
q.add(new TermQuery(new Term(FIELD, "w2"))); Arrays.asList(
booleanQuery.build(),
new TermQuery(new Term(FIELD, "w2"))),
0.5f);
qtest(q, new int[] { 0,1,2,3 }); qtest(q, new int[] { 0,1,2,3 });
} }
public void testDMQ8() throws Exception { public void testDMQ8() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD);
TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5"));
booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD); booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD);
q.add(booleanQuery.build());
TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); 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 }); qtest(q, new int[] { 0,2,3 });
} }
public void testDMQ9() throws Exception { public void testDMQ9() throws Exception {
DisjunctionMaxQuery q = new DisjunctionMaxQuery(0.5f);
BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder(); BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD); booleanQuery.add(new TermQuery(new Term(FIELD, "yy")), BooleanClause.Occur.SHOULD);
TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5")); TermQuery boostedQuery = new TermQuery(new Term(FIELD, "w5"));
booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD); booleanQuery.add(new BoostQuery(boostedQuery, 100), BooleanClause.Occur.SHOULD);
q.add(booleanQuery.build());
TermQuery xxBoostedQuery = new TermQuery(new Term(FIELD, "xx")); 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 }); qtest(q, new int[] { 0,2,3 });
} }

View File

@ -1,5 +1,7 @@
package org.apache.lucene.search; package org.apache.lucene.search;
import java.util.Arrays;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.search.BooleanClause.Occur;
@ -82,9 +84,11 @@ public class TestSimpleSearchEquivalence extends SearchEquivalenceTestBase {
BooleanQuery.Builder q1 = new BooleanQuery.Builder(); BooleanQuery.Builder q1 = new BooleanQuery.Builder();
q1.add(new TermQuery(t1), Occur.SHOULD); q1.add(new TermQuery(t1), Occur.SHOULD);
q1.add(new TermQuery(t2), Occur.SHOULD); q1.add(new TermQuery(t2), Occur.SHOULD);
DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(0.5f); DisjunctionMaxQuery q2 = new DisjunctionMaxQuery(
q2.add(new TermQuery(t1)); Arrays.asList(
q2.add(new TermQuery(t2)); new TermQuery(t1),
new TermQuery(t2)),
0.5f);
assertSameSet(q1.build(), q2); assertSameSet(q1.build(), q2);
} }

View File

@ -18,8 +18,10 @@ package org.apache.lucene.search.highlight;
*/ */
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import com.carrotsearch.randomizedtesting.annotations.Repeat; import com.carrotsearch.randomizedtesting.annotations.Repeat;
import org.apache.lucene.analysis.BaseTokenStreamTestCase; import org.apache.lucene.analysis.BaseTokenStreamTestCase;
import org.apache.lucene.analysis.CannedTokenStream; import org.apache.lucene.analysis.CannedTokenStream;
import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.analysis.MockAnalyzer;
@ -118,9 +120,11 @@ public class TokenSourcesTest extends BaseTokenStreamTestCase {
assertEquals(1, indexReader.numDocs()); assertEquals(1, indexReader.numDocs());
final IndexSearcher indexSearcher = newSearcher(indexReader); final IndexSearcher indexSearcher = newSearcher(indexReader);
try { try {
final DisjunctionMaxQuery query = new DisjunctionMaxQuery(1); final DisjunctionMaxQuery query = new DisjunctionMaxQuery(
query.add(new SpanTermQuery(new Term(FIELD, "{fox}"))); Arrays.asList(
query.add(new SpanTermQuery(new Term(FIELD, "fox"))); new SpanTermQuery(new Term(FIELD, "{fox}")),
new SpanTermQuery(new Term(FIELD, "fox"))),
1);
// final Query phraseQuery = new SpanNearQuery(new SpanQuery[] { // final Query phraseQuery = new SpanNearQuery(new SpanQuery[] {
// new SpanTermQuery(new Term(FIELD, "{fox}")), // new SpanTermQuery(new Term(FIELD, "{fox}")),
// new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true); // new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true);
@ -161,9 +165,11 @@ public class TokenSourcesTest extends BaseTokenStreamTestCase {
try { try {
assertEquals(1, indexReader.numDocs()); assertEquals(1, indexReader.numDocs());
final IndexSearcher indexSearcher = newSearcher(indexReader); final IndexSearcher indexSearcher = newSearcher(indexReader);
final DisjunctionMaxQuery query = new DisjunctionMaxQuery(1); final DisjunctionMaxQuery query = new DisjunctionMaxQuery(
query.add(new SpanTermQuery(new Term(FIELD, "{fox}"))); Arrays.asList(
query.add(new SpanTermQuery(new Term(FIELD, "fox"))); new SpanTermQuery(new Term(FIELD, "{fox}")),
new SpanTermQuery(new Term(FIELD, "fox"))),
1);
// final Query phraseQuery = new SpanNearQuery(new SpanQuery[] { // final Query phraseQuery = new SpanNearQuery(new SpanQuery[] {
// new SpanTermQuery(new Term(FIELD, "{fox}")), // new SpanTermQuery(new Term(FIELD, "{fox}")),
// new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true); // new SpanTermQuery(new Term(FIELD, "fox")) }, 0, true);

View File

@ -17,6 +17,8 @@ package org.apache.lucene.search.postingshighlight;
* limitations under the License. * limitations under the License.
*/ */
import java.util.Collections;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.analysis.MockTokenizer; import org.apache.lucene.analysis.MockTokenizer;
@ -555,8 +557,8 @@ public class TestMultiTermHighlighting extends LuceneTestCase {
return analyzer; return analyzer;
} }
}; };
DisjunctionMaxQuery query = new DisjunctionMaxQuery(0); DisjunctionMaxQuery query = new DisjunctionMaxQuery(
query.add(new WildcardQuery(new Term("body", "te*"))); Collections.singleton(new WildcardQuery(new Term("body", "te*"))), 0);
TopDocs topDocs = searcher.search(query, 10, Sort.INDEXORDER); TopDocs topDocs = searcher.search(query, 10, Sort.INDEXORDER);
assertEquals(2, topDocs.totalHits); assertEquals(2, topDocs.totalHits);
String snippets[] = highlighter.highlight("body", query, searcher, topDocs); String snippets[] = highlighter.highlight("body", query, searcher, topDocs);

View File

@ -19,6 +19,7 @@ package org.apache.lucene.search.vectorhighlight;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -153,11 +154,7 @@ public abstract class AbstractTestCase extends LuceneTestCase {
} }
protected Query dmq( float tieBreakerMultiplier, Query... queries ){ protected Query dmq( float tieBreakerMultiplier, Query... queries ){
DisjunctionMaxQuery query = new DisjunctionMaxQuery( tieBreakerMultiplier ); return new DisjunctionMaxQuery(Arrays.asList(queries), tieBreakerMultiplier);
for( Query q : queries ){
query.add( q );
}
return query;
} }
protected void assertCollectionQueries( Collection<Query> actual, Query... expected ){ protected void assertCollectionQueries( Collection<Query> actual, Query... expected ){

View File

@ -16,6 +16,9 @@ package org.apache.lucene.queryparser.xml.builders;
* limitations under the License. * 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.DOMUtils;
import org.apache.lucene.queryparser.xml.ParserException; import org.apache.lucene.queryparser.xml.ParserException;
import org.apache.lucene.queryparser.xml.QueryBuilder; import org.apache.lucene.queryparser.xml.QueryBuilder;
@ -44,22 +47,22 @@ public class DisjunctionMaxQueryBuilder implements QueryBuilder {
@Override @Override
public Query getQuery(Element e) throws ParserException { public Query getQuery(Element e) throws ParserException {
float tieBreaker = DOMUtils.getAttribute(e, "tieBreaker", 0.0f); float tieBreaker = DOMUtils.getAttribute(e, "tieBreaker", 0.0f);
DisjunctionMaxQuery dq = new DisjunctionMaxQuery(tieBreaker);
List<Query> disjuncts = new ArrayList<>();
NodeList nl = e.getChildNodes(); NodeList nl = e.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) { for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i); Node node = nl.item(i);
if (node instanceof Element) { // all elements are disjuncts. if (node instanceof Element) { // all elements are disjuncts.
Element queryElem = (Element) node; Element queryElem = (Element) node;
Query q = factory.getQuery(queryElem); 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); float boost = DOMUtils.getAttribute(e, "boost", 1.0f);
if (boost != 1f) { if (boost != 1f) {
q = new BoostQuery(dq, boost); q = new BoostQuery(q, boost);
} }
return q; return q;
} }

View File

@ -865,13 +865,8 @@ public class SolrPluginUtils {
if (aliases.containsKey(field)) { if (aliases.containsKey(field)) {
Alias a = aliases.get(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<Query> disjuncts = new ArrayList<>();
for (String f : a.fields.keySet()) { for (String f : a.fields.keySet()) {
Query sub = getFieldQuery(f,queryText,quoted); Query sub = getFieldQuery(f,queryText,quoted);
@ -879,11 +874,12 @@ public class SolrPluginUtils {
if (null != a.fields.get(f)) { if (null != a.fields.get(f)) {
sub = new BoostQuery(sub, a.fields.get(f)); sub = new BoostQuery(sub, a.fields.get(f));
} }
q.add(sub); disjuncts.add(sub);
ok = true;
} }
} }
return ok ? q : null; return disjuncts.isEmpty()
? null
: new DisjunctionMaxQuery(disjuncts, a.tie);
} else { } else {
try { try {

View File

@ -21,7 +21,6 @@ import org.apache.lucene.index.Term;
import org.apache.lucene.search.*; import org.apache.lucene.search.*;
import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.util.AbstractSolrTestCase; import org.apache.solr.util.AbstractSolrTestCase;
import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -72,7 +71,7 @@ public class TestMaxScoreQueryParser extends AbstractSolrTestCase {
assertEquals(1, clauses.length); assertEquals(1, clauses.length);
assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery); assertTrue(clauses[0].getQuery() instanceof DisjunctionMaxQuery);
assertEquals(0.0, ((DisjunctionMaxQuery) clauses[0].getQuery()).getTieBreakerMultiplier(), 1e-15); assertEquals(0.0, ((DisjunctionMaxQuery) clauses[0].getQuery()).getTieBreakerMultiplier(), 1e-15);
ArrayList<Query> qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts(); List<Query> qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts();
assertEquals(2, qa.size()); assertEquals(2, qa.size());
assertEquals("text:foo", qa.get(0).toString()); assertEquals("text:foo", qa.get(0).toString());
} }

View File

@ -38,6 +38,8 @@ import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
@ -419,16 +421,18 @@ public class SolrPluginUtilsTest extends SolrTestCaseJ4 {
/* Simulate stopwords through uneven disjuncts */ /* Simulate stopwords through uneven disjuncts */
q = new BooleanQuery.Builder(); q = new BooleanQuery.Builder();
DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(0.0f); q.add(new DisjunctionMaxQuery(Collections.singleton(new TermQuery(new Term("a","foo"))), 0.0f), Occur.SHOULD);
dmq.add(new TermQuery(new Term("a","foo"))); DisjunctionMaxQuery dmq = new DisjunctionMaxQuery(
Arrays.asList(
new TermQuery(new Term("a","foo")),
new TermQuery(new Term("b","foo"))),
0f);
q.add(dmq, Occur.SHOULD); q.add(dmq, Occur.SHOULD);
dmq = new DisjunctionMaxQuery(0.0f); dmq = new DisjunctionMaxQuery(
dmq.add(new TermQuery(new Term("a","foo"))); Arrays.asList(
dmq.add(new TermQuery(new Term("b","foo"))); new TermQuery(new Term("a","bar")),
q.add(dmq, Occur.SHOULD); new TermQuery(new Term("b","bar"))),
dmq = new DisjunctionMaxQuery(0.0f); 0f);
dmq.add(new TermQuery(new Term("a","bar")));
dmq.add(new TermQuery(new Term("b","bar")));
q.add(dmq, Occur.SHOULD); q.add(dmq, Occur.SHOULD);
// Without relax // Without relax