Internal: move to lucene BoostQuery

Latest version of lucene deprecated Query#setBoost and Query#getBoost which made queries effectively immutable. Those methods need to be replaced with `BoostQuery` that wraps any query that needs boosting.

This commit replaces usages of setBoost with BoostQuery and adds it to forbidden-apis for prod code.

Usages of `getBoost` are only partially removed, as some will have to stay for backwards compatibility.

Closes #14264
This commit is contained in:
javanna 2015-10-23 11:55:28 +02:00 committed by Luca Cavanna
parent 102e25413d
commit 10ddd691a3
44 changed files with 380 additions and 700 deletions

View File

@ -87,3 +87,6 @@ java.util.concurrent.Future#cancel(boolean)
@defaultMessage Don't try reading from paths that are not configured in Environment, resolve from Environment instead
org.elasticsearch.common.io.PathUtils#get(java.lang.String, java.lang.String[])
org.elasticsearch.common.io.PathUtils#get(java.net.URI)
@defaultMessage Don't use deprecated Query#setBoost, wrap the query into a BoostQuery instead
org.apache.lucene.search.Query#setBoost(float)

View File

@ -18,18 +18,9 @@
*/
package org.apache.lucene.queries;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexReaderContext;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.index.TermState;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.InPlaceMergeSorter;
import org.apache.lucene.util.ToStringUtils;
@ -37,6 +28,7 @@ import org.apache.lucene.util.ToStringUtils;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* BlendedTermQuery can be used to unify term statistics across
@ -77,6 +69,10 @@ public abstract class BlendedTermQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
IndexReaderContext context = reader.getContext();
TermContext[] ctx = new TermContext[terms.length];
int[] docFreqs = new int[ctx.length];
@ -87,9 +83,7 @@ public abstract class BlendedTermQuery extends Query {
final int maxDoc = reader.maxDoc();
blend(ctx, maxDoc, reader);
Query query = topLevelQuery(terms, ctx, docFreqs, maxDoc);
query.setBoost(getBoost());
return query;
return topLevelQuery(terms, ctx, docFreqs, maxDoc);
}
protected abstract Query topLevelQuery(Term[] terms, TermContext[] ctx, int[] docFreqs, int maxDoc);
@ -274,20 +268,15 @@ public abstract class BlendedTermQuery extends Query {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
BlendedTermQuery that = (BlendedTermQuery) o;
if (!Arrays.equals(equalsTerms(), that.equalsTerms())) return false;
return true;
return Arrays.equals(equalsTerms(), that.equalsTerms());
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Arrays.hashCode(equalsTerms());
return result;
return Objects.hash(super.hashCode(), Arrays.hashCode(equalsTerms()));
}
public static BlendedTermQuery booleanBlendedQuery(Term[] terms, final boolean disableCoord) {
@ -298,16 +287,16 @@ public abstract class BlendedTermQuery extends Query {
return new BlendedTermQuery(terms, boosts) {
@Override
protected Query topLevelQuery(Term[] terms, TermContext[] ctx, int[] docFreqs, int maxDoc) {
BooleanQuery.Builder query = new BooleanQuery.Builder();
query.setDisableCoord(disableCoord);
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
booleanQueryBuilder.setDisableCoord(disableCoord);
for (int i = 0; i < terms.length; i++) {
TermQuery termQuery = new TermQuery(terms[i], ctx[i]);
if (boosts != null) {
termQuery.setBoost(boosts[i]);
Query query = new TermQuery(terms[i], ctx[i]);
if (boosts != null && boosts[i] != 1f) {
query = new BoostQuery(query, boosts[i]);
}
query.add(termQuery, BooleanClause.Occur.SHOULD);
booleanQueryBuilder.add(query, BooleanClause.Occur.SHOULD);
}
return query.build();
return booleanQueryBuilder.build();
}
};
}
@ -321,16 +310,16 @@ public abstract class BlendedTermQuery extends Query {
BooleanQuery.Builder lowBuilder = new BooleanQuery.Builder();
lowBuilder.setDisableCoord(disableCoord);
for (int i = 0; i < terms.length; i++) {
TermQuery termQuery = new TermQuery(terms[i], ctx[i]);
if (boosts != null) {
termQuery.setBoost(boosts[i]);
Query query = new TermQuery(terms[i], ctx[i]);
if (boosts != null && boosts[i] != 1f) {
query = new BoostQuery(query, boosts[i]);
}
if ((maxTermFrequency >= 1f && docFreqs[i] > maxTermFrequency)
|| (docFreqs[i] > (int) Math.ceil(maxTermFrequency
* (float) maxDoc))) {
highBuilder.add(termQuery, BooleanClause.Occur.SHOULD);
highBuilder.add(query, BooleanClause.Occur.SHOULD);
} else {
lowBuilder.add(termQuery, BooleanClause.Occur.SHOULD);
lowBuilder.add(query, BooleanClause.Occur.SHOULD);
}
}
BooleanQuery high = highBuilder.build();
@ -363,15 +352,15 @@ public abstract class BlendedTermQuery extends Query {
return new BlendedTermQuery(terms, boosts) {
@Override
protected Query topLevelQuery(Term[] terms, TermContext[] ctx, int[] docFreqs, int maxDoc) {
DisjunctionMaxQuery query = new DisjunctionMaxQuery(tieBreakerMultiplier);
DisjunctionMaxQuery disMaxQuery = new DisjunctionMaxQuery(tieBreakerMultiplier);
for (int i = 0; i < terms.length; i++) {
TermQuery termQuery = new TermQuery(terms[i], ctx[i]);
if (boosts != null) {
termQuery.setBoost(boosts[i]);
Query query = new TermQuery(terms[i], ctx[i]);
if (boosts != null && boosts[i] != 1f) {
query = new BoostQuery(query, boosts[i]);
}
query.add(termQuery);
disMaxQuery.add(query);
}
return query;
return disMaxQuery;
}
};
}

View File

@ -29,6 +29,7 @@ import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import java.io.IOException;
import java.util.Objects;
/** A {@link Query} that only matches documents that are greater than or equal
* to a configured doc ID. */
@ -43,7 +44,7 @@ public final class MinDocQuery extends Query {
@Override
public int hashCode() {
return 31 * super.hashCode() + minDoc;
return Objects.hash(super.hashCode(), minDoc);
}
@Override

View File

@ -23,13 +23,7 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.*;
import org.apache.lucene.util.IOUtils;
import org.apache.lucene.util.automaton.RegExp;
import org.elasticsearch.common.lucene.search.Queries;
@ -41,12 +35,7 @@ import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.support.QueryParsers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import static java.util.Collections.unmodifiableMap;
import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded;
@ -148,8 +137,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getFieldQuerySingle(mField, queryText, quoted);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -161,8 +149,7 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = getFieldQuerySingle(mField, queryText, quoted);
if (q != null) {
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -250,9 +237,8 @@ public class MapperQueryParser extends QueryParser {
Query q = super.getFieldQuery(mField, queryText, slop);
if (q != null) {
added = true;
applyBoost(mField, q);
q = applySlop(q, slop);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -264,9 +250,8 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = super.getFieldQuery(mField, queryText, slop);
if (q != null) {
applyBoost(mField, q);
q = applySlop(q, slop);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -305,8 +290,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getRangeQuerySingle(mField, part1, part2, startInclusive, endInclusive);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -318,8 +302,7 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = getRangeQuerySingle(mField, part1, part2, startInclusive, endInclusive);
if (q != null) {
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -371,8 +354,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getFuzzyQuerySingle(mField, termStr, minSimilarity);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -383,8 +365,9 @@ public class MapperQueryParser extends QueryParser {
List<BooleanClause> clauses = new ArrayList<>();
for (String mField : fields) {
Query q = getFuzzyQuerySingle(mField, termStr, minSimilarity);
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
if (q != null) {
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
return getBooleanQuery(clauses, true);
}
@ -434,8 +417,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getPrefixQuerySingle(mField, termStr);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -447,8 +429,7 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = getPrefixQuerySingle(mField, termStr);
if (q != null) {
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -566,8 +547,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getWildcardQuerySingle(mField, termStr);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -579,8 +559,7 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = getWildcardQuerySingle(mField, termStr);
if (q != null) {
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -697,8 +676,7 @@ public class MapperQueryParser extends QueryParser {
Query q = getRegexpQuerySingle(mField, termStr);
if (q != null) {
added = true;
applyBoost(mField, q);
disMaxQuery.add(q);
disMaxQuery.add(applyBoost(mField, q));
}
}
if (!added) {
@ -710,8 +688,7 @@ public class MapperQueryParser extends QueryParser {
for (String mField : fields) {
Query q = getRegexpQuerySingle(mField, termStr);
if (q != null) {
applyBoost(mField, q);
clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
clauses.add(new BooleanClause(applyBoost(mField, q), BooleanClause.Occur.SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
@ -761,11 +738,12 @@ public class MapperQueryParser extends QueryParser {
return fixNegativeQueryIfNeeded(q);
}
private void applyBoost(String field, Query q) {
private Query applyBoost(String field, Query q) {
Float fieldBoost = settings.fieldsAndWeights().get(field);
if (fieldBoost != null) {
q.setBoost(fieldBoost);
if (fieldBoost != null && fieldBoost != 1f) {
return new BoostQuery(q, fieldBoost);
}
return q;
}
private Query applySlop(Query q, int slop) {
@ -779,7 +757,9 @@ public class MapperQueryParser extends QueryParser {
builder.add(terms[i], positions[i]);
}
pq = builder.build();
pq.setBoost(q.getBoost());
//make sure that the boost hasn't been set beforehand, otherwise we'd lose it
assert q.getBoost() == 1f;
assert q instanceof BoostQuery == false;
return pq;
} else if (q instanceof MultiPhraseQuery) {
((MultiPhraseQuery) q).setSlop(slop);

View File

@ -22,11 +22,7 @@ package org.apache.lucene.search.vectorhighlight;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.BlendedTermQuery;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.*;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
@ -103,8 +99,7 @@ public class CustomFieldQuery extends FieldQuery {
for (int i = 0; i < termsIdx.length; i++) {
queryBuilder.add(terms.get(i)[termsIdx[i]], pos[i]);
}
PhraseQuery query = queryBuilder.build();
query.setBoost(orig.getBoost());
Query query = queryBuilder.build();
this.flatten(query, reader, flatQueries, orig.getBoost());
} else {
Term[] t = terms.get(currentPos);

View File

@ -64,8 +64,9 @@ public final class AllTermQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1f) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
boolean fieldExists = false;
boolean hasPayloads = false;
@ -80,14 +81,10 @@ public final class AllTermQuery extends Query {
}
}
if (fieldExists == false) {
Query rewritten = new MatchNoDocsQuery();
rewritten.setBoost(getBoost());
return rewritten;
return new MatchNoDocsQuery();
}
if (hasPayloads == false) {
TermQuery rewritten = new TermQuery(term);
rewritten.setBoost(getBoost());
return rewritten;
return new TermQuery(term);
}
return this;
}

View File

@ -35,10 +35,7 @@ import org.elasticsearch.common.io.FastStringReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
*
@ -79,29 +76,17 @@ public class MoreLikeThisQuery extends Query {
@Override
public int hashCode() {
int result = boostTerms ? 1 : 0;
result = 31 * result + Float.floatToIntBits(boostTermsFactor);
result = 31 * result + Arrays.hashCode(likeText);
result = 31 * result + maxDocFreq;
result = 31 * result + maxQueryTerms;
result = 31 * result + maxWordLen;
result = 31 * result + minDocFreq;
result = 31 * result + minTermFrequency;
result = 31 * result + minWordLen;
result = 31 * result + Arrays.hashCode(moreLikeFields);
result = 31 * result + minimumShouldMatch.hashCode();
result = 31 * result + (stopWords == null ? 0 : stopWords.hashCode());
result = 31 * result + Float.floatToIntBits(getBoost());
return result;
return Objects.hash(super.hashCode(), boostTerms, boostTermsFactor, Arrays.hashCode(likeText),
maxDocFreq, maxQueryTerms, maxWordLen, minDocFreq, minTermFrequency, minWordLen,
Arrays.hashCode(moreLikeFields), minimumShouldMatch, stopWords);
}
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass())
if (super.equals(obj) == false) {
return false;
}
MoreLikeThisQuery other = (MoreLikeThisQuery) obj;
if (getBoost() != other.getBoost())
return false;
if (!analyzer.equals(other.analyzer))
return false;
if (boostTerms != other.boostTerms)
@ -141,6 +126,10 @@ public class MoreLikeThisQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
XMoreLikeThis mlt = new XMoreLikeThis(reader, similarity == null ? new DefaultSimilarity() : similarity);
mlt.setFieldNames(moreLikeFields);
@ -179,10 +168,7 @@ public class MoreLikeThisQuery extends Query {
mltQuery = Queries.applyMinimumShouldMatch((BooleanQuery) mltQuery, minimumShouldMatch);
bqBuilder.add(mltQuery, BooleanClause.Occur.SHOULD);
}
BooleanQuery bq = bqBuilder.build();
bq.setBoost(getBoost());
return bq;
return bqBuilder.build();
}
private void handleUnlike(XMoreLikeThis mlt, String[] unlikeText, Fields[] unlikeFields) throws IOException {

View File

@ -120,8 +120,9 @@ public class MultiPhrasePrefixQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1.0F) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
if (termArrays.isEmpty()) {
return new MatchNoDocsQuery();
@ -145,7 +146,6 @@ public class MultiPhrasePrefixQuery extends Query {
return Queries.newMatchNoDocsQuery();
}
query.add(terms.toArray(Term.class), position);
query.setBoost(getBoost());
return query.rewrite(reader);
}
@ -233,10 +233,11 @@ public class MultiPhrasePrefixQuery extends Query {
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof MultiPhrasePrefixQuery)) return false;
if (super.equals(o) == false) {
return false;
}
MultiPhrasePrefixQuery other = (MultiPhrasePrefixQuery) o;
return this.getBoost() == other.getBoost()
&& this.slop == other.slop
return this.slop == other.slop
&& termArraysEquals(this.termArrays, other.termArrays)
&& this.positions.equals(other.positions);
}
@ -246,11 +247,10 @@ public class MultiPhrasePrefixQuery extends Query {
*/
@Override
public int hashCode() {
return Float.floatToIntBits(getBoost())
return super.hashCode()
^ slop
^ termArraysHashCode()
^ positions.hashCode()
^ 0x4AC65113;
^ positions.hashCode();
}
// Breakout calculation of the termArrays hashcode

View File

@ -70,7 +70,7 @@ public class Queries {
.build();
}
public static boolean isNegativeQuery(Query q) {
private static boolean isNegativeQuery(Query q) {
if (!(q instanceof BooleanQuery)) {
return false;
}
@ -107,7 +107,7 @@ public class Queries {
return false;
}
public static BooleanQuery applyMinimumShouldMatch(BooleanQuery query, @Nullable String minimumShouldMatch) {
public static Query applyMinimumShouldMatch(BooleanQuery query, @Nullable String minimumShouldMatch) {
if (minimumShouldMatch == null) {
return query;
}
@ -127,10 +127,13 @@ public class Queries {
}
builder.setMinimumNumberShouldMatch(msm);
BooleanQuery bq = builder.build();
bq.setBoost(query.getBoost());
query = bq;
if (query.getBoost() != 1f) {
return new BoostQuery(bq, query.getBoost());
}
return bq;
} else {
return query;
}
return query;
}
private static Pattern spaceAroundLessThanPattern = Pattern.compile("(\\s+<\\s*)|(\\s*<\\s+)");

View File

@ -670,14 +670,14 @@ public final class XMoreLikeThis {
float bestScore = -1;
while ((scoreTerm = q.pop()) != null) {
TermQuery tq = new TermQuery(new Term(scoreTerm.topField, scoreTerm.word));
Query tq = new TermQuery(new Term(scoreTerm.topField, scoreTerm.word));
if (boost) {
if (bestScore == -1) {
bestScore = (scoreTerm.score);
}
float myScore = (scoreTerm.score);
tq.setBoost(boostFactor * myScore / bestScore);
tq = new BoostQuery(tq, boostFactor * myScore / bestScore);
}
try {

View File

@ -123,8 +123,9 @@ public class FiltersFunctionScoreQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1.0F) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
Query newQ = subQuery.rewrite(reader);
if (newQ == subQuery)

View File

@ -71,8 +71,9 @@ public class FunctionScoreQuery extends Query {
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1.0F) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
Query newQ = subQuery.rewrite(reader);
if (newQ == subQuery) {

View File

@ -219,8 +219,9 @@ public class DateFieldMapper extends NumberFieldMapper {
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1.0F) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
return innerRangeQuery(lowerTerm, upperTerm, includeLower, includeUpper, timeZone, forcedDateParser);
}
@ -229,11 +230,9 @@ public class DateFieldMapper extends NumberFieldMapper {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
LateParsingQuery that = (LateParsingQuery) o;
if (includeLower != that.includeLower) return false;
if (includeUpper != that.includeUpper) return false;
if (lowerTerm != null ? !lowerTerm.equals(that.lowerTerm) : that.lowerTerm != null) return false;
@ -245,13 +244,7 @@ public class DateFieldMapper extends NumberFieldMapper {
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (lowerTerm != null ? lowerTerm.hashCode() : 0);
result = 31 * result + (upperTerm != null ? upperTerm.hashCode() : 0);
result = 31 * result + (includeLower ? 1 : 0);
result = 31 * result + (includeUpper ? 1 : 0);
result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
return result;
return Objects.hash(super.hashCode(), lowerTerm, upperTerm, includeLower, includeUpper, timeZone);
}
@Override

View File

@ -19,7 +19,10 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.ParseField;
@ -74,7 +77,13 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder> exte
public final Query toQuery(QueryShardContext context) throws IOException {
Query query = doToQuery(context);
if (query != null) {
setFinalBoost(query);
if (boost != DEFAULT_BOOST) {
if (query instanceof SpanQuery) {
query = new SpanBoostQuery((SpanQuery) query, boost);
} else {
query = new BoostQuery(query, boost);
}
}
if (queryName != null) {
context.addNamedQuery(queryName, query);
}
@ -82,20 +91,6 @@ public abstract class AbstractQueryBuilder<QB extends AbstractQueryBuilder> exte
return query;
}
/**
* Sets the main boost to the query obtained by converting the current query into a lucene query.
* The default behaviour is to set the main boost, after verifying that we are not overriding any non default boost
* value that was previously set to the lucene query. That case would require some manual decision on how to combine
* the main boost with the boost coming from lucene by overriding this method.
* @throws IllegalStateException if the lucene query boost has already been set
*/
protected void setFinalBoost(Query query) {
if (query.getBoost() != AbstractQueryBuilder.DEFAULT_BOOST) {
throw new IllegalStateException("lucene query boost is already set, override setFinalBoost to define how to combine lucene boost with main boost");
}
query.setBoost(boost);
}
@Override
public final Query toFilter(QueryShardContext context) throws IOException {
Query result = null;

View File

@ -279,8 +279,8 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
} else {
minimumShouldMatch = this.minimumShouldMatch;
}
booleanQuery = Queries.applyMinimumShouldMatch(booleanQuery, minimumShouldMatch);
return adjustPureNegative ? fixNegativeQueryIfNeeded(booleanQuery) : booleanQuery;
Query query = Queries.applyMinimumShouldMatch(booleanQuery, minimumShouldMatch);
return adjustPureNegative ? fixNegativeQueryIfNeeded(query) : query;
}
private static void addBooleanClauses(QueryShardContext context, BooleanQuery.Builder booleanQueryBuilder, List<QueryBuilder> clauses, Occur occurs) throws IOException {

View File

@ -215,8 +215,6 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
if (innerQuery == null) {
return null;
}
innerQuery.setBoost(boost);
DocumentMapper childDocMapper = context.getMapperService().documentMapper(type);
if (childDocMapper == null) {
throw new QueryShardException(context, "[" + NAME + "] no mapping found for type [" + type + "]");
@ -286,8 +284,9 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
@Override
public Query rewrite(IndexReader reader) throws IOException {
if (getBoost() != 1.0F) {
return super.rewrite(reader);
Query rewritten = super.rewrite(reader);
if (rewritten != this) {
return rewritten;
}
if (reader instanceof DirectoryReader) {
String joinField = ParentFieldMapper.joinField(parentType);
@ -310,8 +309,6 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
LateParsingQuery that = (LateParsingQuery) o;
@ -326,14 +323,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + toQuery.hashCode();
result = 31 * result + innerQuery.hashCode();
result = 31 * result + minChildren;
result = 31 * result + maxChildren;
result = 31 * result + parentType.hashCode();
result = 31 * result + scoreMode.hashCode();
return result;
return Objects.hash(super.hashCode(), toQuery, innerQuery, minChildren, maxChildren, parentType, scoreMode);
}
@Override

View File

@ -129,7 +129,6 @@ public class HasParentQueryBuilder extends AbstractQueryBuilder<HasParentQueryBu
if (innerQuery == null) {
return null;
}
innerQuery.setBoost(boost);
DocumentMapper parentDocMapper = context.getMapperService().documentMapper(type);
if (parentDocMapper == null) {
throw new QueryShardException(context, "[has_parent] query configured 'parent_type' [" + type

View File

@ -115,14 +115,6 @@ public class IndicesQueryBuilder extends AbstractQueryBuilder<IndicesQueryBuilde
return noMatchQuery.toQuery(context);
}
@Override
protected void setFinalBoost(Query query) {
if (boost != DEFAULT_BOOST) {
//if both the wrapped query and the wrapper hold a boost, the main one coming from the wrapper wins
query.setBoost(boost);
}
}
@Override
protected IndicesQueryBuilder doReadFrom(StreamInput in) throws IOException {
IndicesQueryBuilder indicesQueryBuilder = new IndicesQueryBuilder(in.readQuery(), in.readStringArray());

View File

@ -301,8 +301,7 @@ public class MatchQueryBuilder extends AbstractQueryBuilder<MatchQueryBuilder> {
}
/**
* Get the setting for handling zero terms queries.
* @see #zeroTermsQuery(ZeroTermsQuery)
* Returns the setting for handling zero terms queries.
*/
public MatchQuery.ZeroTermsQuery zeroTermsQuery() {
return this.zeroTermsQuery;

View File

@ -548,12 +548,6 @@ public class MultiMatchQueryBuilder extends AbstractQueryBuilder<MultiMatchQuery
return query;
}
@Override
protected void setFinalBoost(Query query) {
// we need to preserve the boost that came out of the parsing phase
query.setBoost(boost * query.getBoost());
}
private static Map<String, Float> handleFieldsMatchPattern(MapperService mapperService, Map<String, Float> fieldsBoosts) {
Map<String, Float> newFieldsBoosts = new TreeMap<>();
for (Map.Entry<String, Float> fieldBoost : fieldsBoosts.entrySet()) {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.queryparser.classic.MapperQueryParser;
import org.apache.lucene.queryparser.classic.QueryParserSettings;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.automaton.Operations;
@ -36,10 +37,7 @@ import org.elasticsearch.index.query.support.QueryParsers;
import org.joda.time.DateTimeZone;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.*;
/**
* A query that parses a query string and runs it. There are two modes that this operates. The first,
@ -722,16 +720,25 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
if (query == null) {
return null;
}
//save the BoostQuery wrapped structure if present
List<Float> boosts = new ArrayList<>();
while(query instanceof BoostQuery) {
BoostQuery boostQuery = (BoostQuery) query;
boosts.add(boostQuery.getBoost());
query = boostQuery.getQuery();
}
query = Queries.fixNegativeQueryIfNeeded(query);
if (query instanceof BooleanQuery) {
query = Queries.applyMinimumShouldMatch((BooleanQuery) query, this.minimumShouldMatch());
}
//restore the previous BoostQuery wrapping
for (int i = boosts.size() - 1; i >= 0; i--) {
query = new BoostQuery(query, boosts.get(i));
}
return query;
}
@Override
protected void setFinalBoost(Query query) {
//we need to preserve the boost that came out of the parsing phase
query.setBoost(query.getBoost() * boost);
}
}

View File

@ -104,10 +104,7 @@ public class ScriptQueryBuilder extends AbstractQueryBuilder<ScriptQueryBuilder>
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hashCode(script);
return result;
return Objects.hash(super.hashCode(), script);
}
@Override

View File

@ -63,8 +63,7 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
try {
Query q = createBooleanQuery(entry.getKey(), text, super.getDefaultOperator());
if (q != null) {
q.setBoost(entry.getValue());
bq.add(q, BooleanClause.Occur.SHOULD);
bq.add(wrapWithBoost(q, entry.getValue()), BooleanClause.Occur.SHOULD);
}
} catch (RuntimeException e) {
rethrowUnlessLenient(e);
@ -86,9 +85,8 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
bq.setDisableCoord(true);
for (Map.Entry<String,Float> entry : weights.entrySet()) {
try {
Query q = new FuzzyQuery(new Term(entry.getKey(), text), fuzziness);
q.setBoost(entry.getValue());
bq.add(q, BooleanClause.Occur.SHOULD);
Query query = new FuzzyQuery(new Term(entry.getKey(), text), fuzziness);
bq.add(wrapWithBoost(query, entry.getValue()), BooleanClause.Occur.SHOULD);
} catch (RuntimeException e) {
rethrowUnlessLenient(e);
}
@ -104,8 +102,7 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
try {
Query q = createPhraseQuery(entry.getKey(), text, slop);
if (q != null) {
q.setBoost(entry.getValue());
bq.add(q, BooleanClause.Occur.SHOULD);
bq.add(wrapWithBoost(q, entry.getValue()), BooleanClause.Occur.SHOULD);
}
} catch (RuntimeException e) {
rethrowUnlessLenient(e);
@ -129,12 +126,12 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
try {
if (settings.analyzeWildcard()) {
Query analyzedQuery = newPossiblyAnalyzedQuery(entry.getKey(), text);
analyzedQuery.setBoost(entry.getValue());
bq.add(analyzedQuery, BooleanClause.Occur.SHOULD);
if (analyzedQuery != null) {
bq.add(wrapWithBoost(analyzedQuery, entry.getValue()), BooleanClause.Occur.SHOULD);
}
} else {
PrefixQuery prefix = new PrefixQuery(new Term(entry.getKey(), text));
prefix.setBoost(entry.getValue());
bq.add(prefix, BooleanClause.Occur.SHOULD);
Query query = new PrefixQuery(new Term(entry.getKey(), text));
bq.add(wrapWithBoost(query, entry.getValue()), BooleanClause.Occur.SHOULD);
}
} catch (RuntimeException e) {
return rethrowUnlessLenient(e);
@ -143,6 +140,13 @@ public class SimpleQueryParser extends org.apache.lucene.queryparser.simple.Simp
return super.simplify(bq.build());
}
private static Query wrapWithBoost(Query query, float boost) {
if (boost != AbstractQueryBuilder.DEFAULT_BOOST) {
return new BoostQuery(query, boost);
}
return query;
}
/**
* Analyze the given string using its analyzer, constructing either a
* {@code PrefixQuery} or a {@code BooleanQuery} made up

View File

@ -299,11 +299,6 @@ public class SimpleQueryStringBuilder extends AbstractQueryBuilder<SimpleQuerySt
return fieldName;
}
@Override
protected void setFinalBoost(Query query) {
query.setBoost(boost * query.getBoost());
}
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);

View File

@ -18,9 +18,12 @@
*/
package org.elasticsearch.index.query;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.search.spans.SpanQuery;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -62,11 +65,23 @@ public class SpanMultiTermQueryBuilder extends AbstractQueryBuilder<SpanMultiTer
@Override
protected Query doToQuery(QueryShardContext context) throws IOException {
Query subQuery = multiTermQueryBuilder.toQuery(context);
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
if (subQuery instanceof BoostQuery) {
BoostQuery boostQuery = (BoostQuery) subQuery;
subQuery = boostQuery.getQuery();
boost = boostQuery.getBoost();
}
//no MultiTermQuery extends SpanQuery, so SpanBoostQuery is not supported here
assert subQuery instanceof SpanBoostQuery == false;
if (subQuery instanceof MultiTermQuery == false) {
throw new UnsupportedOperationException("unsupported inner query, should be " + MultiTermQuery.class.getName() +" but was "
+ subQuery.getClass().getName());
}
return new SpanMultiTermQueryWrapper<>((MultiTermQuery) subQuery);
SpanQuery wrapper = new SpanMultiTermQueryWrapper<>((MultiTermQuery) subQuery);
if (boost != AbstractQueryBuilder.DEFAULT_BOOST) {
wrapper = new SpanBoostQuery(wrapper, boost);
}
return wrapper;
}
@Override

View File

@ -110,11 +110,6 @@ public class TemplateQueryBuilder extends AbstractQueryBuilder<TemplateQueryBuil
}
}
@Override
protected void setFinalBoost(Query query) {
//no-op this query doesn't support boost
}
@Override
protected TemplateQueryBuilder doReadFrom(StreamInput in) throws IOException {
TemplateQueryBuilder templateQueryBuilder = new TemplateQueryBuilder(Template.readTemplate(in));

View File

@ -115,11 +115,6 @@ public class WrapperQueryBuilder extends AbstractQueryBuilder<WrapperQueryBuilde
}
}
@Override
protected void setFinalBoost(Query query) {
//no-op this query doesn't support boost
}
@Override
protected WrapperQueryBuilder doReadFrom(StreamInput in) throws IOException {
return new WrapperQueryBuilder(in.readByteArray());

View File

@ -22,14 +22,12 @@ package org.elasticsearch.index.search;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.BlendedTermQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.*;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.AbstractQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryShardContext;
@ -56,8 +54,8 @@ public class MultiMatchQuery extends MatchQuery {
if (query instanceof BooleanQuery) {
query = Queries.applyMinimumShouldMatch((BooleanQuery) query, minimumShouldMatch);
}
if (boostValue != null && query != null) {
query.setBoost(boostValue);
if (query != null && boostValue != null && boostValue != AbstractQueryBuilder.DEFAULT_BOOST) {
query = new BoostQuery(query, boostValue);
}
return query;
}
@ -167,13 +165,13 @@ public class MultiMatchQuery extends MatchQuery {
Analyzer actualAnalyzer = getAnalyzer(fieldType);
name = fieldType.names().indexName();
if (!groups.containsKey(actualAnalyzer)) {
groups.put(actualAnalyzer, new ArrayList<FieldAndFieldType>());
groups.put(actualAnalyzer, new ArrayList<>());
}
Float boost = entry.getValue();
boost = boost == null ? Float.valueOf(1.0f) : boost;
groups.get(actualAnalyzer).add(new FieldAndFieldType(name, fieldType, boost));
} else {
missing.add(new Tuple(name, entry.getValue()));
missing.add(new Tuple<>(name, entry.getValue()));
}
}

View File

@ -30,6 +30,7 @@ import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
import java.util.Objects;
/**
*
@ -94,11 +95,7 @@ public class InMemoryGeoBoundingBoxQuery extends Query {
@Override
public int hashCode() {
int h = super.hashCode();
h = 31 * h + fieldName().hashCode();
h = 31 * h + topLeft.hashCode();
h = 31 * h + bottomRight.hashCode();
return h;
return Objects.hash(super.hashCode(), fieldName(), topLeft, bottomRight);
}
private static class Meridian180GeoBoundingBoxBits implements Bits {

View File

@ -1,295 +0,0 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.search.nested;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorer;
import org.apache.lucene.search.Weight;
import org.apache.lucene.search.join.BitSetProducer;
import org.apache.lucene.util.BitSet;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
/**
* A special query that accepts a top level parent matching query, and returns the nested docs of the matching parent
* doc as well. This is handy when deleting by query, don't use it for other purposes.
*
* @elasticsearch.internal
*/
public class IncludeNestedDocsQuery extends Query {
private final BitSetProducer parentFilter;
private final Query parentQuery;
// If we are rewritten, this is the original childQuery we
// were passed; we use this for .equals() and
// .hashCode(). This makes rewritten query equal the
// original, so that user does not have to .rewrite() their
// query before searching:
private final Query origParentQuery;
public IncludeNestedDocsQuery(Query parentQuery, BitSetProducer parentFilter) {
this.origParentQuery = parentQuery;
this.parentQuery = parentQuery;
this.parentFilter = parentFilter;
}
// For rewriting
IncludeNestedDocsQuery(Query rewrite, Query originalQuery, IncludeNestedDocsQuery previousInstance) {
this.origParentQuery = originalQuery;
this.parentQuery = rewrite;
this.parentFilter = previousInstance.parentFilter;
setBoost(previousInstance.getBoost());
}
// For cloning
IncludeNestedDocsQuery(Query originalQuery, IncludeNestedDocsQuery previousInstance) {
this.origParentQuery = originalQuery;
this.parentQuery = originalQuery;
this.parentFilter = previousInstance.parentFilter;
}
@Override
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
return new IncludeNestedDocsWeight(this, parentQuery, parentQuery.createWeight(searcher, needsScores), parentFilter);
}
static class IncludeNestedDocsWeight extends Weight {
private final Query parentQuery;
private final Weight parentWeight;
private final BitSetProducer parentsFilter;
IncludeNestedDocsWeight(Query query, Query parentQuery, Weight parentWeight, BitSetProducer parentsFilter) {
super(query);
this.parentQuery = parentQuery;
this.parentWeight = parentWeight;
this.parentsFilter = parentsFilter;
}
@Override
public void extractTerms(Set<Term> terms) {
parentWeight.extractTerms(terms);
}
@Override
public void normalize(float norm, float topLevelBoost) {
parentWeight.normalize(norm, topLevelBoost);
}
@Override
public float getValueForNormalization() throws IOException {
return parentWeight.getValueForNormalization(); // this query is never boosted so just delegate...
}
@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
final Scorer parentScorer = parentWeight.scorer(context);
// no matches
if (parentScorer == null) {
return null;
}
BitSet parents = parentsFilter.getBitSet(context);
if (parents == null) {
// No matches
return null;
}
int firstParentDoc = parentScorer.nextDoc();
if (firstParentDoc == DocIdSetIterator.NO_MORE_DOCS) {
// No matches
return null;
}
return new IncludeNestedDocsScorer(this, parentScorer, parents, firstParentDoc);
}
@Override
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
return null; //Query is used internally and not by users, so explain can be empty
}
}
static class IncludeNestedDocsScorer extends Scorer {
final Scorer parentScorer;
final BitSet parentBits;
int currentChildPointer = -1;
int currentParentPointer = -1;
int currentDoc = -1;
IncludeNestedDocsScorer(Weight weight, Scorer parentScorer, BitSet parentBits, int currentParentPointer) {
super(weight);
this.parentScorer = parentScorer;
this.parentBits = parentBits;
this.currentParentPointer = currentParentPointer;
if (currentParentPointer == 0) {
currentChildPointer = 0;
} else {
this.currentChildPointer = this.parentBits.prevSetBit(currentParentPointer - 1);
if (currentChildPointer == -1) {
// no previous set parent, we delete from doc 0
currentChildPointer = 0;
} else {
currentChildPointer++; // we only care about children
}
}
currentDoc = currentChildPointer;
}
@Override
public Collection<ChildScorer> getChildren() {
return parentScorer.getChildren();
}
@Override
public int nextDoc() throws IOException {
if (currentParentPointer == NO_MORE_DOCS) {
return (currentDoc = NO_MORE_DOCS);
}
if (currentChildPointer == currentParentPointer) {
// we need to return the current parent as well, but prepare to return
// the next set of children
currentDoc = currentParentPointer;
currentParentPointer = parentScorer.nextDoc();
if (currentParentPointer != NO_MORE_DOCS) {
currentChildPointer = parentBits.prevSetBit(currentParentPointer - 1);
if (currentChildPointer == -1) {
// no previous set parent, just set the child to the current parent
currentChildPointer = currentParentPointer;
} else {
currentChildPointer++; // we only care about children
}
}
} else {
currentDoc = currentChildPointer++;
}
assert currentDoc != -1;
return currentDoc;
}
@Override
public int advance(int target) throws IOException {
if (target == NO_MORE_DOCS) {
return (currentDoc = NO_MORE_DOCS);
}
if (target == 0) {
return nextDoc();
}
if (target < currentParentPointer) {
currentDoc = currentParentPointer = parentScorer.advance(target);
if (currentParentPointer == NO_MORE_DOCS) {
return (currentDoc = NO_MORE_DOCS);
}
if (currentParentPointer == 0) {
currentChildPointer = 0;
} else {
currentChildPointer = parentBits.prevSetBit(currentParentPointer - 1);
if (currentChildPointer == -1) {
// no previous set parent, just set the child to 0 to delete all up to the parent
currentChildPointer = 0;
} else {
currentChildPointer++; // we only care about children
}
}
} else {
currentDoc = currentChildPointer++;
}
return currentDoc;
}
@Override
public float score() throws IOException {
return parentScorer.score();
}
@Override
public int freq() throws IOException {
return parentScorer.freq();
}
@Override
public int docID() {
return currentDoc;
}
@Override
public long cost() {
return parentScorer.cost();
}
}
@Override
public Query rewrite(IndexReader reader) throws IOException {
final Query parentRewrite = parentQuery.rewrite(reader);
if (parentRewrite != parentQuery) {
return new IncludeNestedDocsQuery(parentRewrite, parentQuery, this);
} else {
return this;
}
}
@Override
public String toString(String field) {
return "IncludeNestedDocsQuery (" + parentQuery.toString() + ")";
}
@Override
public boolean equals(Object _other) {
if (_other instanceof IncludeNestedDocsQuery) {
final IncludeNestedDocsQuery other = (IncludeNestedDocsQuery) _other;
return origParentQuery.equals(other.origParentQuery) && parentFilter.equals(other.parentFilter);
} else {
return false;
}
}
@Override
public int hashCode() {
final int prime = 31;
int hash = 1;
hash = prime * hash + origParentQuery.hashCode();
hash = prime * hash + parentFilter.hashCode();
return hash;
}
@Override
public Query clone() {
Query clonedQuery = origParentQuery.clone();
return new IncludeNestedDocsQuery(clonedQuery, this);
}
}

View File

@ -41,6 +41,7 @@ import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.query.AbstractQueryBuilder;
import org.elasticsearch.index.query.ParsedQuery;
import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.index.similarity.SimilarityService;
@ -196,14 +197,16 @@ public class DefaultSearchContext extends SearchContext {
if (query() == null) {
parsedQuery(ParsedQuery.parsedMatchAllQuery());
}
if (queryBoost() != 1.0f) {
if (queryBoost() != AbstractQueryBuilder.DEFAULT_BOOST) {
parsedQuery(new ParsedQuery(new FunctionScoreQuery(query(), new WeightFactorFunction(queryBoost)), parsedQuery()));
}
Query searchFilter = searchFilter(types());
if (searchFilter != null) {
if (Queries.isConstantMatchAllQuery(query())) {
Query q = new ConstantScoreQuery(searchFilter);
q.setBoost(query().getBoost());
if (query().getBoost() != AbstractQueryBuilder.DEFAULT_BOOST) {
q = new BoostQuery(q, query().getBoost());
}
parsedQuery(new ParsedQuery(q, parsedQuery()));
} else {
BooleanQuery filtered = new BooleanQuery.Builder()

View File

@ -27,6 +27,7 @@ import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.RAMDirectory;
@ -34,6 +35,7 @@ import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.test.ESTestCase;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
public class MultiPhrasePrefixQueryTests extends ESTestCase {
public void testSimple() throws Exception {
@ -78,6 +80,8 @@ public class MultiPhrasePrefixQueryTests extends ESTestCase {
multiPhrasePrefixQuery.add(new Term[]{new Term("field", "aaa"), new Term("field", "bb")});
multiPhrasePrefixQuery.setBoost(randomFloat());
Query query = multiPhrasePrefixQuery.rewrite(reader);
assertThat(query.getBoost(), equalTo(multiPhrasePrefixQuery.getBoost()));
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(multiPhrasePrefixQuery.getBoost()));
}
}

View File

@ -23,8 +23,12 @@ import com.carrotsearch.randomizedtesting.generators.CodepointSetGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.Accountable;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
@ -104,9 +108,7 @@ import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.*;
public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>> extends ESTestCase {
@ -501,26 +503,45 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
assertThat(namedQuery, equalTo(query));
}
if (query != null) {
assertBoost(queryBuilder, query);
if (queryBuilder.boost() != AbstractQueryBuilder.DEFAULT_BOOST) {
assertThat(query, either(instanceOf(BoostQuery.class)).or(instanceOf(SpanBoostQuery.class)));
if (query instanceof SpanBoostQuery) {
SpanBoostQuery spanBoostQuery = (SpanBoostQuery) query;
assertThat(spanBoostQuery.getBoost(), equalTo(queryBuilder.boost()));
query = spanBoostQuery.getQuery();
} else {
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(queryBuilder.boost()));
query = boostQuery.getQuery();
}
}
}
doAssertLuceneQuery(queryBuilder, query, context);
}
/**
* Allows to override boost assertions for queries that don't have the default behaviour
*/
protected void assertBoost(QB queryBuilder, Query query) throws IOException {
// workaround https://bugs.openjdk.java.net/browse/JDK-8056984
float boost = queryBuilder.boost();
assertThat(query.getBoost(), equalTo(boost));
}
/**
* Checks the result of {@link QueryBuilder#toQuery(QueryShardContext)} given the original {@link QueryBuilder} and {@link QueryShardContext}.
* Contains the query specific checks to be implemented by subclasses.
*/
protected abstract void doAssertLuceneQuery(QB queryBuilder, Query query, QueryShardContext context) throws IOException;
protected static void assertTermOrBoostQuery(Query query, String field, String value, float fieldBoost) {
if (fieldBoost != AbstractQueryBuilder.DEFAULT_BOOST) {
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(fieldBoost));
query = boostQuery.getQuery();
}
assertTermQuery(query, field, value);
}
protected static void assertTermQuery(Query query, String field, String value) {
assertThat(query, instanceOf(TermQuery.class));
TermQuery termQuery = (TermQuery) query;
assertThat(termQuery.getTerm().field(), equalTo(field));
assertThat(termQuery.getTerm().text().toLowerCase(Locale.ROOT), equalTo(value.toLowerCase(Locale.ROOT)));
}
/**
* Test serialization and deserialization of the test query.
*/

View File

@ -20,21 +20,16 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.*;
public class DisMaxQueryBuilderTests extends AbstractQueryTestCase<DisMaxQueryBuilder> {
/**
@ -138,9 +133,13 @@ public class DisMaxQueryBuilderTests extends AbstractQueryTestCase<DisMaxQueryBu
List<Query> disjuncts = disjunctionMaxQuery.getDisjuncts();
assertThat(disjuncts.size(), equalTo(1));
PrefixQuery firstQ = (PrefixQuery) disjuncts.get(0);
assertThat(disjuncts.get(0), instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) disjuncts.get(0);
assertThat((double) boostQuery.getBoost(), closeTo(1.2, 0.00001));
assertThat(boostQuery.getQuery(), instanceOf(PrefixQuery.class));
PrefixQuery firstQ = (PrefixQuery) boostQuery.getQuery();
// since age is automatically registered in data, we encode it as numeric
assertThat(firstQ.getPrefix(), equalTo(new Term(STRING_FIELD_NAME, "sh")));
assertThat((double) firstQ.getBoost(), closeTo(1.2, 0.00001));
}
}

View File

@ -20,6 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
@ -116,12 +117,15 @@ public class FuzzyQueryBuilderTests extends AbstractQueryTestCase<FuzzyQueryBuil
" }\n" +
"}";
Query parsedQuery = parseQuery(query).toQuery(createShardContext());
assertThat(parsedQuery, instanceOf(FuzzyQuery.class));
FuzzyQuery fuzzyQuery = (FuzzyQuery) parsedQuery;
assertThat(parsedQuery, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) parsedQuery;
assertThat(boostQuery.getBoost(), equalTo(2.0f));
assertThat(boostQuery.getQuery(), instanceOf(FuzzyQuery.class));
FuzzyQuery fuzzyQuery = (FuzzyQuery) boostQuery.getQuery();
assertThat(fuzzyQuery.getTerm(), equalTo(new Term(STRING_FIELD_NAME, "sh")));
assertThat(fuzzyQuery.getMaxEdits(), equalTo(Fuzziness.AUTO.asDistance("sh")));
assertThat(fuzzyQuery.getPrefixLength(), equalTo(1));
assertThat(fuzzyQuery.getBoost(), equalTo(2.0f));
}
public void testToQueryWithNumericField() throws IOException {
@ -130,8 +134,7 @@ public class FuzzyQueryBuilderTests extends AbstractQueryTestCase<FuzzyQueryBuil
" \"fuzzy\":{\n" +
" \"" + INT_FIELD_NAME + "\":{\n" +
" \"value\":12,\n" +
" \"fuzziness\":5,\n" +
" \"boost\":2.0\n" +
" \"fuzziness\":5\n" +
" }\n" +
" }\n" +
"}\n";

View File

@ -56,15 +56,7 @@ public class IndicesQueryBuilderTests extends AbstractQueryTestCase<IndicesQuery
} else {
expected = queryBuilder.noMatchQuery().toQuery(context);
}
if (expected != null && queryBuilder.boost() != AbstractQueryBuilder.DEFAULT_BOOST) {
expected.setBoost(queryBuilder.boost());
}
assertEquals(query, expected);
}
@Override
protected void assertBoost(IndicesQueryBuilder queryBuilder, Query query) throws IOException {
//nothing to do here, boost check is already included in equality check done as part of doAssertLuceneQuery above
assertEquals(expected, query);
}
public void testIllegalArguments() {

View File

@ -20,13 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.queries.ExtendedCommonTermsQuery;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.*;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.index.mapper.MappedFieldType;
@ -50,12 +44,12 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
if (fieldName.equals(DATE_FIELD_NAME)) {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
}
Object value = "";
Object value;
if (fieldName.equals(STRING_FIELD_NAME)) {
int terms = randomIntBetween(0, 3);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < terms; i++) {
builder.append(randomAsciiOfLengthBetween(1, 10) + " ");
builder.append(randomAsciiOfLengthBetween(1, 10)).append(" ");
}
value = builder.toString().trim();
} else {
@ -139,8 +133,6 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
queryValue = queryValue.toLowerCase(Locale.ROOT);
}
Query expectedTermQuery = fieldType.termQuery(queryValue, context);
// the real query will have boost applied, so we set it to our expeced as well
expectedTermQuery.setBoost(queryBuilder.boost());
assertEquals(expectedTermQuery, query);
}
@ -174,7 +166,7 @@ public class MatchQueryBuilderTests extends AbstractQueryTestCase<MatchQueryBuil
// depending on analyzer being set or not we can have term lowercased along the way, so to simplify test we just
// compare lowercased terms here
String originalTermLc = queryBuilder.value().toString().toLowerCase(Locale.ROOT);
String actualTermLc = fuzzyQuery.getTerm().text().toString().toLowerCase(Locale.ROOT);
String actualTermLc = fuzzyQuery.getTerm().text().toLowerCase(Locale.ROOT);
assertThat(actualTermLc, equalTo(originalTermLc));
assertThat(queryBuilder.prefixLength(), equalTo(fuzzyQuery.getPrefixLength()));
assertThat(queryBuilder.fuzzyTranspositions(), equalTo(fuzzyQuery.getTranspositions()));

View File

@ -21,14 +21,7 @@ package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.ExtendedCommonTermsQuery;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.*;
import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
import org.elasticsearch.index.search.MatchQuery;
@ -127,7 +120,7 @@ public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatc
@Override
protected void doAssertLuceneQuery(MultiMatchQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
// we rely on integration tests for deeper checks here
assertThat(query, either(instanceOf(TermQuery.class)).or(instanceOf(AllTermQuery.class))
assertThat(query, either(instanceOf(BoostQuery.class)).or(instanceOf(TermQuery.class)).or(instanceOf(AllTermQuery.class))
.or(instanceOf(BooleanQuery.class)).or(instanceOf(DisjunctionMaxQuery.class))
.or(instanceOf(FuzzyQuery.class)).or(instanceOf(MultiPhrasePrefixQuery.class))
.or(instanceOf(MatchAllDocsQuery.class)).or(instanceOf(ExtendedCommonTermsQuery.class))
@ -164,26 +157,22 @@ public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatc
}
}
@Override
protected void assertBoost(MultiMatchQueryBuilder queryBuilder, Query query) throws IOException {
//we delegate boost checks to specific boost tests below
}
public void testToQueryBoost() throws IOException {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
QueryShardContext shardContext = createShardContext();
MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder("test");
multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5);
multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5f);
Query query = multiMatchQueryBuilder.toQuery(shardContext);
assertThat(query, instanceOf(TermQuery.class));
assertThat(query.getBoost(), equalTo(5f));
assertTermOrBoostQuery(query, STRING_FIELD_NAME, "test", 5f);
multiMatchQueryBuilder = new MultiMatchQueryBuilder("test");
multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5);
multiMatchQueryBuilder.boost(2);
multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5f);
multiMatchQueryBuilder.boost(2f);
query = multiMatchQueryBuilder.toQuery(shardContext);
assertThat(query, instanceOf(TermQuery.class));
assertThat(query.getBoost(), equalTo(10f));
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(2f));
assertTermOrBoostQuery(boostQuery.getQuery(), STRING_FIELD_NAME, "test", 5f);
}
public void testToQueryMultipleTermsBooleanQuery() throws Exception {
@ -212,7 +201,9 @@ public class MultiMatchQueryBuilderTests extends AbstractQueryTestCase<MultiMatc
assertThat(query, instanceOf(DisjunctionMaxQuery.class));
DisjunctionMaxQuery disMaxQuery = (DisjunctionMaxQuery) query;
List<Query> disjuncts = disMaxQuery.getDisjuncts();
assertThat(disjuncts.get(0), instanceOf(TermQuery.class));
assertThat(((TermQuery) disjuncts.get(0)).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test")));
assertThat(disjuncts.get(1), instanceOf(TermQuery.class));
assertThat(((TermQuery) disjuncts.get(1)).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
}

View File

@ -20,16 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.*;
import org.apache.lucene.util.automaton.TooComplexToDeterminizeException;
import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.hamcrest.Matchers;
@ -42,9 +33,8 @@ import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBooleanSubQuery;
import static org.hamcrest.CoreMatchers.either;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStringQueryBuilder> {
@ -197,13 +187,17 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
Query query = queryStringQuery.toQuery(shardContext);
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), Matchers.equalTo(2.0f));
assertThat(boostQuery.getBoost(), equalTo(2.0f));
assertThat(boostQuery.getQuery(), instanceOf(TermQuery.class));
assertThat(((TermQuery) boostQuery.getQuery()).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "boosted")));
queryStringQuery.boost(2.0f);
query = queryStringQuery.toQuery(shardContext);
assertThat(query, instanceOf(BoostQuery.class));
assertThat(((BoostQuery) query).getBoost(), Matchers.equalTo(4.0f));
boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(2.0f));
assertThat(boostQuery .getQuery(), instanceOf(BoostQuery.class));
boostQuery = (BoostQuery) boostQuery.getQuery();
assertThat(boostQuery.getBoost(), equalTo(2.0f));
queryStringQuery = queryStringQuery("((" + STRING_FIELD_NAME + ":boosted^2) AND (" + STRING_FIELD_NAME + ":foo^1.5))^3");
query = queryStringQuery.toQuery(shardContext);
@ -222,7 +216,7 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
query = queryStringQuery.toQuery(shardContext);
assertThat(query, instanceOf(BoostQuery.class));
boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(6.0f));
assertThat(boostQuery.getBoost(), equalTo(2.0f));
}
public void testToQueryMultipleTermsBooleanQuery() throws Exception {
@ -271,10 +265,8 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
assertThat(query, instanceOf(DisjunctionMaxQuery.class));
DisjunctionMaxQuery disMaxQuery = (DisjunctionMaxQuery) query;
List<Query> disjuncts = disMaxQuery.getDisjuncts();
assertThat(((TermQuery) disjuncts.get(0)).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test")));
assertThat((double) disjuncts.get(0).getBoost(), closeTo(2.2, 0.01));
assertThat(((TermQuery) disjuncts.get(1)).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
assertThat((double) disjuncts.get(1).getBoost(), closeTo(1, 0.01));
assertTermOrBoostQuery(disjuncts.get(0), STRING_FIELD_NAME, "test", 2.2f);
assertTermOrBoostQuery(disjuncts.get(1), STRING_FIELD_NAME_2, "test", 1.0f);
}
public void testToQueryRegExpQuery() throws Exception {
@ -330,4 +322,56 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
// We expect this one
}
}
public void testToQueryBooleanQueryMultipleBoosts() throws Exception {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
int numBoosts = randomIntBetween(2, 10);
float[] boosts = new float[numBoosts + 1];
String queryStringPrefix = "";
String queryStringSuffix = "";
for (int i = 0; i < boosts.length - 1; i++) {
float boost = 2.0f / randomIntBetween(3, 20);
boosts[i] = boost;
queryStringPrefix += "(";
queryStringSuffix += ")^" + boost;
}
String queryString = queryStringPrefix + "foo bar" + queryStringSuffix;
float mainBoost = 2.0f / randomIntBetween(3, 20);
boosts[boosts.length - 1] = mainBoost;
QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(queryString).field(STRING_FIELD_NAME)
.minimumShouldMatch("2").boost(mainBoost);
Query query = queryStringQueryBuilder.toQuery(createShardContext());
for (int i = boosts.length - 1; i >= 0; i--) {
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(boosts[i]));
query = boostQuery.getQuery();
}
assertThat(query, instanceOf(BooleanQuery.class));
BooleanQuery booleanQuery = (BooleanQuery) query;
assertThat(booleanQuery.getMinimumNumberShouldMatch(), equalTo(2));
assertThat(booleanQuery.clauses().get(0).getOccur(), equalTo(BooleanClause.Occur.SHOULD));
assertThat(booleanQuery.clauses().get(0).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "foo"))));
assertThat(booleanQuery.clauses().get(1).getOccur(), equalTo(BooleanClause.Occur.SHOULD));
assertThat(booleanQuery.clauses().get(1).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "bar"))));
}
public void testToQueryPhraseQueryBoostAndSlop() throws IOException {
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder("\"test phrase\"~2").field(STRING_FIELD_NAME, 5f);
Query query = queryStringQueryBuilder.toQuery(createShardContext());
assertThat(query, instanceOf(DisjunctionMaxQuery.class));
DisjunctionMaxQuery disjunctionMaxQuery = (DisjunctionMaxQuery) query;
assertThat(disjunctionMaxQuery.getDisjuncts().size(), equalTo(1));
assertThat(disjunctionMaxQuery.getDisjuncts().get(0), instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) disjunctionMaxQuery.getDisjuncts().get(0);
assertThat(boostQuery.getBoost(), equalTo(5f));
assertThat(boostQuery.getQuery(), instanceOf(PhraseQuery.class));
PhraseQuery phraseQuery = (PhraseQuery) boostQuery.getQuery();
assertThat(phraseQuery.getSlop(), Matchers.equalTo(2));
assertThat(phraseQuery.getTerms().length, equalTo(2));
}
}

View File

@ -61,27 +61,38 @@ public class RandomQueryBuilder {
public static MultiTermQueryBuilder createMultiTermQuery(Random r) {
// for now, only use String Rangequeries for MultiTerm test, numeric and date makes little sense
// see issue #12123 for discussion
MultiTermQueryBuilder<?> multiTermQueryBuilder;
switch(RandomInts.randomIntBetween(r, 0, 5)) {
case 0:
RangeQueryBuilder stringRangeQuery = new RangeQueryBuilder(AbstractQueryTestCase.STRING_FIELD_NAME);
stringRangeQuery.from("a" + RandomStrings.randomAsciiOfLengthBetween(r, 1, 10));
stringRangeQuery.to("z" + RandomStrings.randomAsciiOfLengthBetween(r, 1, 10));
return stringRangeQuery;
multiTermQueryBuilder = stringRangeQuery;
break;
case 1:
RangeQueryBuilder numericRangeQuery = new RangeQueryBuilder(AbstractQueryTestCase.INT_FIELD_NAME);
numericRangeQuery.from(RandomInts.randomIntBetween(r, 1, 100));
numericRangeQuery.to(RandomInts.randomIntBetween(r, 101, 200));
return numericRangeQuery;
multiTermQueryBuilder = numericRangeQuery;
break;
case 2:
return new FuzzyQueryBuilder(AbstractQueryTestCase.INT_FIELD_NAME, RandomInts.randomInt(r, 1000));
multiTermQueryBuilder = new FuzzyQueryBuilder(AbstractQueryTestCase.INT_FIELD_NAME, RandomInts.randomInt(r, 1000));
break;
case 3:
return new FuzzyQueryBuilder(AbstractQueryTestCase.STRING_FIELD_NAME, RandomStrings.randomAsciiOfLengthBetween(r, 1, 10));
multiTermQueryBuilder = new FuzzyQueryBuilder(AbstractQueryTestCase.STRING_FIELD_NAME, RandomStrings.randomAsciiOfLengthBetween(r, 1, 10));
break;
case 4:
return new PrefixQueryBuilderTests().createTestQueryBuilder();
multiTermQueryBuilder = new PrefixQueryBuilderTests().createTestQueryBuilder();
break;
case 5:
return new WildcardQueryBuilderTests().createTestQueryBuilder();
multiTermQueryBuilder = new WildcardQueryBuilderTests().createTestQueryBuilder();
break;
default:
throw new UnsupportedOperationException();
}
if (r.nextBoolean()) {
multiTermQueryBuilder.boost(2.0f / RandomInts.randomIntBetween(r, 1, 20));
}
return multiTermQueryBuilder;
}
}

View File

@ -20,11 +20,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.*;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.ParseFieldMatcher;
@ -276,10 +272,9 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
assertThat(query, notNullValue());
if ("".equals(queryBuilder.value())) {
assertTrue("Query should have been MatchNoDocsQuery but was " + query.getClass().getName(), query instanceof MatchNoDocsQuery);
assertThat(query, instanceOf(MatchNoDocsQuery.class));
} else if (queryBuilder.fields().size() > 1) {
assertTrue("Query should have been BooleanQuery but was " + query.getClass().getName(), query instanceof BooleanQuery);
assertThat(query, instanceOf(BooleanQuery.class));
BooleanQuery boolQuery = (BooleanQuery) query;
if (queryBuilder.lowercaseExpandedTerms()) {
for (BooleanClause clause : boolQuery.clauses()) {
@ -289,43 +284,26 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
}
}
}
assertThat(boolQuery.clauses().size(), equalTo(queryBuilder.fields().size()));
Iterator<String> fields = queryBuilder.fields().keySet().iterator();
Iterator<Map.Entry<String, Float>> fieldsIterator = queryBuilder.fields().entrySet().iterator();
for (BooleanClause booleanClause : boolQuery) {
assertThat(booleanClause.getQuery(), instanceOf(TermQuery.class));
TermQuery termQuery = (TermQuery) booleanClause.getQuery();
assertThat(termQuery.getTerm().field(), equalTo(fields.next()));
assertThat(termQuery.getTerm().text().toLowerCase(Locale.ROOT), equalTo(queryBuilder.value().toLowerCase(Locale.ROOT)));
Map.Entry<String, Float> field = fieldsIterator.next();
assertTermOrBoostQuery(booleanClause.getQuery(), field.getKey(), queryBuilder.value(), field.getValue());
}
if (queryBuilder.minimumShouldMatch() != null) {
assertThat(boolQuery.getMinimumNumberShouldMatch(), greaterThan(0));
}
} else if (queryBuilder.fields().size() <= 1) {
assertTrue("Query should have been TermQuery but was " + query.getClass().getName(), query instanceof TermQuery);
TermQuery termQuery = (TermQuery) query;
String field;
if (queryBuilder.fields().size() == 0) {
field = MetaData.ALL;
} else {
field = queryBuilder.fields().keySet().iterator().next();
}
assertThat(termQuery.getTerm().field(), equalTo(field));
assertThat(termQuery.getTerm().text().toLowerCase(Locale.ROOT), equalTo(queryBuilder.value().toLowerCase(Locale.ROOT)));
} else if (queryBuilder.fields().size() == 1) {
Map.Entry<String, Float> field = queryBuilder.fields().entrySet().iterator().next();
assertTermOrBoostQuery(query, field.getKey(), queryBuilder.value(), field.getValue());
} else if (queryBuilder.fields().size() == 0) {
assertTermQuery(query, MetaData.ALL, queryBuilder.value());
} else {
fail("Encountered lucene query type we do not have a validation implementation for in our " + SimpleQueryStringBuilderTests.class.getSimpleName());
}
}
@Override
protected void assertBoost(SimpleQueryStringBuilder queryBuilder, Query query) throws IOException {
//boost may get parsed from the random query, we then combine the main boost with that one coming from lucene
//instead of trying to reparse the query and guess what the boost should be, we delegate boost checks to specific boost tests below
}
private int shouldClauses(BooleanQuery query) {
private static int shouldClauses(BooleanQuery query) {
int result = 0;
for (BooleanClause c : query.clauses()) {
if (c.getOccur() == BooleanClause.Occur.SHOULD) {
@ -341,15 +319,21 @@ public class SimpleQueryStringBuilderTests extends AbstractQueryTestCase<SimpleQ
SimpleQueryStringBuilder simpleQueryStringBuilder = new SimpleQueryStringBuilder("test");
simpleQueryStringBuilder.field(STRING_FIELD_NAME, 5);
Query query = simpleQueryStringBuilder.toQuery(shardContext);
assertThat(query, instanceOf(TermQuery.class));
assertThat(query.getBoost(), equalTo(5f));
assertThat(query, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(5f));
assertThat(boostQuery.getQuery(), instanceOf(TermQuery.class));
simpleQueryStringBuilder = new SimpleQueryStringBuilder("test");
simpleQueryStringBuilder.field(STRING_FIELD_NAME, 5);
simpleQueryStringBuilder.boost(2);
query = simpleQueryStringBuilder.toQuery(shardContext);
assertThat(query, instanceOf(TermQuery.class));
assertThat(query.getBoost(), equalTo(10f));
boostQuery = (BoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(2f));
assertThat(boostQuery.getQuery(), instanceOf(BoostQuery.class));
boostQuery = (BoostQuery) boostQuery.getQuery();
assertThat(boostQuery.getBoost(), equalTo(5f));
assertThat(boostQuery.getQuery(), instanceOf(TermQuery.class));
}
public void testNegativeFlags() throws IOException {

View File

@ -19,9 +19,12 @@
package org.elasticsearch.index.query;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanBoostQuery;
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.search.spans.SpanQuery;
import java.io.IOException;
@ -37,9 +40,20 @@ public class SpanMultiTermQueryBuilderTests extends AbstractQueryTestCase<SpanMu
@Override
protected void doAssertLuceneQuery(SpanMultiTermQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
if (queryBuilder.innerQuery().boost() != AbstractQueryBuilder.DEFAULT_BOOST) {
assertThat(query, instanceOf(SpanBoostQuery.class));
SpanBoostQuery boostQuery = (SpanBoostQuery) query;
assertThat(boostQuery.getBoost(), equalTo(queryBuilder.innerQuery().boost()));
query = boostQuery.getQuery();
}
assertThat(query, instanceOf(SpanMultiTermQueryWrapper.class));
SpanMultiTermQueryWrapper spanMultiTermQueryWrapper = (SpanMultiTermQueryWrapper) query;
Query multiTermQuery = queryBuilder.innerQuery().toQuery(context);
if (queryBuilder.innerQuery().boost() != AbstractQueryBuilder.DEFAULT_BOOST) {
assertThat(multiTermQuery, instanceOf(BoostQuery.class));
BoostQuery boostQuery = (BoostQuery) multiTermQuery;
multiTermQuery = boostQuery.getQuery();
}
assertThat(multiTermQuery, instanceOf(MultiTermQuery.class));
assertThat(spanMultiTermQueryWrapper.getWrappedQuery(), equalTo(new SpanMultiTermQueryWrapper<>((MultiTermQuery)multiTermQuery).getWrappedQuery()));
}
@ -72,4 +86,10 @@ public class SpanMultiTermQueryBuilderTests extends AbstractQueryTestCase<SpanMu
}
}
}
public void testToQueryInnerSpanMultiTerm() throws IOException {
Query query = new SpanOrQueryBuilder(createTestQueryBuilder()).toQuery(createShardContext());
//verify that the result is still a span query, despite the boost that might get set (SpanBoostQuery rather than BoostQuery)
assertThat(query, instanceOf(SpanQuery.class));
}
}

View File

@ -68,11 +68,6 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
}
}
@Override
protected void assertBoost(TemplateQueryBuilder queryBuilder, Query query) throws IOException {
//no-op boost is checked already above as part of doAssertLuceneQuery as we rely on lucene equals impl
}
/**
* Override superclass test since template query doesn't support boost and queryName, so
* we need to mutate other existing field in the test query.

View File

@ -64,11 +64,6 @@ public class WrapperQueryBuilderTests extends AbstractQueryTestCase<WrapperQuery
}
}
@Override
protected void assertBoost(WrapperQueryBuilder queryBuilder, Query query) throws IOException {
//no-op boost is checked already above as part of doAssertLuceneQuery as we rely on lucene equals impl
}
public void testIllegalArgument() {
try {
if (randomBoolean()) {