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.
(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

View File

@ -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<Query> {
/* 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. */
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<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) {
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<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"));
this.disjuncts = disjuncts.toArray(new Query[disjuncts.size()]);
}
/** @return An {@code Iterator<Query>} over the disjuncts */
@Override
public Iterator<Query> iterator() {
return disjuncts.iterator();
return getDisjuncts().iterator();
}
/**
* @return the disjuncts.
*/
public ArrayList<Query> getDisjuncts() {
return disjuncts;
public List<Query> getDisjuncts() {
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) */
@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<Query> 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<Query>
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<Query>
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<Query>
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;
}

View File

@ -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();

View File

@ -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<Query> 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<Query> 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<Query> 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 });
}

View File

@ -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;

View File

@ -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<Query> 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();
}

View File

@ -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 });
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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<Query> actual, Query... expected ){

View File

@ -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<Query> 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;
}

View File

@ -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<Query> 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 {

View File

@ -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<Query> qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts();
List<Query> qa = ((DisjunctionMaxQuery) clauses[0].getQuery()).getDisjuncts();
assertEquals(2, qa.size());
assertEquals("text:foo", qa.get(0).toString());
}

View File

@ -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