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:
parent
102e25413d
commit
10ddd691a3
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,11 +127,14 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
private static Pattern spaceAroundLessThanPattern = Pattern.compile("(\\s+<\\s*)|(\\s*<\\s+)");
|
||||
private static Pattern spacePattern = Pattern.compile(" ");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
return query;
|
||||
|
||||
//restore the previous BoostQuery wrapping
|
||||
for (int i = boosts.size() - 1; i >= 0; i--) {
|
||||
query = new BoostQuery(query, boosts.get(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFinalBoost(Query query) {
|
||||
//we need to preserve the boost that came out of the parsing phase
|
||||
query.setBoost(query.getBoost() * boost);
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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")));
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue