parent
274611c7c0
commit
484fcd49e5
|
@ -19,20 +19,12 @@
|
|||
|
||||
package org.apache.lucene.queryparser.classic;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
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.FilteredQuery;
|
||||
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.WildcardQuery;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.apache.lucene.util.automaton.RegExp;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
|
@ -42,8 +34,6 @@ import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
|||
import org.elasticsearch.index.query.QueryShardContext;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
@ -74,17 +64,8 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
private QueryParserSettings settings;
|
||||
|
||||
private Analyzer quoteAnalyzer;
|
||||
|
||||
private boolean forcedAnalyzer;
|
||||
private boolean forcedQuoteAnalyzer;
|
||||
|
||||
private MappedFieldType currentFieldType;
|
||||
|
||||
private boolean analyzeWildcard;
|
||||
|
||||
private String quoteFieldSuffix;
|
||||
|
||||
public MapperQueryParser(QueryShardContext context) {
|
||||
super(null, null);
|
||||
this.context = context;
|
||||
|
@ -92,31 +73,14 @@ public class MapperQueryParser extends QueryParser {
|
|||
|
||||
public void reset(QueryParserSettings settings) {
|
||||
this.settings = settings;
|
||||
this.field = settings.defaultField();
|
||||
|
||||
if (settings.fields() != null) {
|
||||
if (settings.fields.size() == 1) {
|
||||
// just mark it as the default field
|
||||
this.field = settings.fields().get(0);
|
||||
} else {
|
||||
// otherwise, we need to have the default field being null...
|
||||
this.field = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.forcedAnalyzer = settings.forcedAnalyzer() != null;
|
||||
this.setAnalyzer(forcedAnalyzer ? settings.forcedAnalyzer() : settings.defaultAnalyzer());
|
||||
if (settings.forcedQuoteAnalyzer() != null) {
|
||||
this.forcedQuoteAnalyzer = true;
|
||||
this.quoteAnalyzer = settings.forcedQuoteAnalyzer();
|
||||
} else if (forcedAnalyzer) {
|
||||
this.forcedQuoteAnalyzer = true;
|
||||
this.quoteAnalyzer = settings.forcedAnalyzer();
|
||||
if (settings.fieldsAndWeights().isEmpty()) {
|
||||
this.field = settings.defaultField();
|
||||
} else if (settings.fieldsAndWeights().size() == 1) {
|
||||
this.field = settings.fieldsAndWeights().keySet().iterator().next();
|
||||
} else {
|
||||
this.forcedAnalyzer = false;
|
||||
this.quoteAnalyzer = settings.defaultQuoteAnalyzer();
|
||||
this.field = null;
|
||||
}
|
||||
this.quoteFieldSuffix = settings.quoteFieldSuffix();
|
||||
setAnalyzer(settings.analyzer());
|
||||
setMultiTermRewriteMethod(settings.rewriteMethod());
|
||||
setEnablePositionIncrements(settings.enablePositionIncrements());
|
||||
setAutoGeneratePhraseQueries(settings.autoGeneratePhraseQueries());
|
||||
|
@ -125,10 +89,9 @@ public class MapperQueryParser extends QueryParser {
|
|||
setLowercaseExpandedTerms(settings.lowercaseExpandedTerms());
|
||||
setPhraseSlop(settings.phraseSlop());
|
||||
setDefaultOperator(settings.defaultOperator());
|
||||
setFuzzyMinSim(settings.getFuzziness().asFloat());
|
||||
setFuzzyMinSim(settings.fuzziness().asFloat());
|
||||
setFuzzyPrefixLength(settings.fuzzyPrefixLength());
|
||||
setLocale(settings.locale());
|
||||
this.analyzeWildcard = settings.analyzeWildcard();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,9 +187,9 @@ public class MapperQueryParser extends QueryParser {
|
|||
Analyzer oldAnalyzer = getAnalyzer();
|
||||
try {
|
||||
if (quoted) {
|
||||
setAnalyzer(quoteAnalyzer);
|
||||
if (quoteFieldSuffix != null) {
|
||||
currentFieldType = context.fieldMapper(field + quoteFieldSuffix);
|
||||
setAnalyzer(settings.quoteAnalyzer());
|
||||
if (settings.quoteFieldSuffix() != null) {
|
||||
currentFieldType = context.fieldMapper(field + settings.quoteFieldSuffix());
|
||||
}
|
||||
}
|
||||
if (currentFieldType == null) {
|
||||
|
@ -234,11 +197,11 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
if (currentFieldType != null) {
|
||||
if (quoted) {
|
||||
if (!forcedQuoteAnalyzer) {
|
||||
if (!settings.forceQuoteAnalyzer()) {
|
||||
setAnalyzer(context.getSearchQuoteAnalyzer(currentFieldType));
|
||||
}
|
||||
} else {
|
||||
if (!forcedAnalyzer) {
|
||||
if (!settings.forceAnalyzer()) {
|
||||
setAnalyzer(context.getSearchAnalyzer(currentFieldType));
|
||||
}
|
||||
}
|
||||
|
@ -494,7 +457,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
try {
|
||||
currentFieldType = context.fieldMapper(field);
|
||||
if (currentFieldType != null) {
|
||||
if (!forcedAnalyzer) {
|
||||
if (!settings.forceAnalyzer()) {
|
||||
setAnalyzer(context.getSearchAnalyzer(currentFieldType));
|
||||
}
|
||||
Query query = null;
|
||||
|
@ -518,7 +481,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
|
||||
private Query getPossiblyAnalyzedPrefixQuery(String field, String termStr) throws ParseException {
|
||||
if (!analyzeWildcard) {
|
||||
if (!settings.analyzeWildcard()) {
|
||||
return super.getPrefixQuery(field, termStr);
|
||||
}
|
||||
// get Analyzer from superclass and tokenize the term
|
||||
|
@ -556,16 +519,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
clauses.add(new BooleanClause(super.getPrefixQuery(field, token), BooleanClause.Occur.SHOULD));
|
||||
}
|
||||
return getBooleanQuery(clauses, true);
|
||||
|
||||
//return super.getPrefixQuery(field, termStr);
|
||||
|
||||
/* this means that the analyzer used either added or consumed
|
||||
* (common for a stemmer) tokens, and we can't build a PrefixQuery */
|
||||
// throw new ParseException("Cannot build PrefixQuery with analyzer "
|
||||
// + getAnalyzer().getClass()
|
||||
// + (tlist.size() > 1 ? " - token(s) added" : " - token consumed"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -635,7 +589,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
try {
|
||||
currentFieldType = context.fieldMapper(field);
|
||||
if (currentFieldType != null) {
|
||||
if (!forcedAnalyzer) {
|
||||
if (!settings.forceAnalyzer()) {
|
||||
setAnalyzer(context.getSearchAnalyzer(currentFieldType));
|
||||
}
|
||||
indexedNameField = currentFieldType.names().indexName();
|
||||
|
@ -653,7 +607,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
|
||||
private Query getPossiblyAnalyzedWildcardQuery(String field, String termStr) throws ParseException {
|
||||
if (!analyzeWildcard) {
|
||||
if (!settings.analyzeWildcard()) {
|
||||
return super.getWildcardQuery(field, termStr);
|
||||
}
|
||||
boolean isWithinToken = (!termStr.startsWith("?") && !termStr.startsWith("*"));
|
||||
|
@ -767,7 +721,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
try {
|
||||
currentFieldType = context.fieldMapper(field);
|
||||
if (currentFieldType != null) {
|
||||
if (!forcedAnalyzer) {
|
||||
if (!settings.forceAnalyzer()) {
|
||||
setAnalyzer(context.getSearchAnalyzer(currentFieldType));
|
||||
}
|
||||
Query query = null;
|
||||
|
@ -800,9 +754,9 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
|
||||
private void applyBoost(String field, Query q) {
|
||||
if (settings.boosts() != null) {
|
||||
float boost = settings.boosts().getOrDefault(field, 1f);
|
||||
q.setBoost(boost);
|
||||
Float fieldBoost = settings.fieldsAndWeights().get(field);
|
||||
if (fieldBoost != null) {
|
||||
q.setBoost(fieldBoost);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -828,11 +782,11 @@ public class MapperQueryParser extends QueryParser {
|
|||
}
|
||||
|
||||
private Collection<String> extractMultiFields(String field) {
|
||||
Collection<String> fields = null;
|
||||
Collection<String> fields;
|
||||
if (field != null) {
|
||||
fields = context.simpleMatchToIndexNames(field);
|
||||
} else {
|
||||
fields = settings.fields();
|
||||
fields = settings.fieldsAndWeights().keySet();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
|
|
@ -19,66 +19,74 @@
|
|||
|
||||
package org.apache.lucene.queryparser.classic;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectFloatHashMap;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.MultiTermQuery;
|
||||
import org.apache.lucene.util.automaton.Operations;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* Encapsulates settings that affect query_string parsing via {@link MapperQueryParser}
|
||||
*/
|
||||
public class QueryParserSettings {
|
||||
|
||||
public static final boolean DEFAULT_ALLOW_LEADING_WILDCARD = true;
|
||||
public static final boolean DEFAULT_ANALYZE_WILDCARD = false;
|
||||
public static final float DEFAULT_BOOST = 1.f;
|
||||
private final String queryString;
|
||||
|
||||
private String queryString;
|
||||
private String defaultField;
|
||||
private float boost = DEFAULT_BOOST;
|
||||
private MapperQueryParser.Operator defaultOperator = QueryParser.Operator.OR;
|
||||
private boolean autoGeneratePhraseQueries = false;
|
||||
private boolean allowLeadingWildcard = DEFAULT_ALLOW_LEADING_WILDCARD;
|
||||
private boolean lowercaseExpandedTerms = true;
|
||||
private boolean enablePositionIncrements = true;
|
||||
private int phraseSlop = 0;
|
||||
private Fuzziness fuzziness = Fuzziness.AUTO;
|
||||
private int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
|
||||
private int fuzzyMaxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
private int maxDeterminizedStates = Operations.DEFAULT_MAX_DETERMINIZED_STATES;
|
||||
private MultiTermQuery.RewriteMethod fuzzyRewriteMethod = null;
|
||||
private boolean analyzeWildcard = DEFAULT_ANALYZE_WILDCARD;
|
||||
private boolean escape = false;
|
||||
private Analyzer defaultAnalyzer = null;
|
||||
private Analyzer defaultQuoteAnalyzer = null;
|
||||
private Analyzer forcedAnalyzer = null;
|
||||
private Analyzer forcedQuoteAnalyzer = null;
|
||||
private String quoteFieldSuffix = null;
|
||||
private MultiTermQuery.RewriteMethod rewriteMethod = MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE;
|
||||
private String minimumShouldMatch;
|
||||
private boolean lenient;
|
||||
|
||||
private Map<String, Float> fieldsAndWeights;
|
||||
|
||||
private QueryParser.Operator defaultOperator;
|
||||
|
||||
private Analyzer analyzer;
|
||||
private boolean forceAnalyzer;
|
||||
private Analyzer quoteAnalyzer;
|
||||
private boolean forceQuoteAnalyzer;
|
||||
|
||||
private String quoteFieldSuffix;
|
||||
|
||||
private boolean autoGeneratePhraseQueries;
|
||||
|
||||
private boolean allowLeadingWildcard;
|
||||
|
||||
private boolean analyzeWildcard;
|
||||
|
||||
private boolean lowercaseExpandedTerms;
|
||||
|
||||
private boolean enablePositionIncrements;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
private Fuzziness fuzziness;
|
||||
private int fuzzyPrefixLength;
|
||||
private int fuzzyMaxExpansions;
|
||||
private MultiTermQuery.RewriteMethod fuzzyRewriteMethod;
|
||||
|
||||
private int phraseSlop;
|
||||
|
||||
private boolean useDisMax;
|
||||
|
||||
private float tieBreaker;
|
||||
|
||||
private MultiTermQuery.RewriteMethod rewriteMethod;
|
||||
|
||||
private boolean lenient;
|
||||
|
||||
private DateTimeZone timeZone;
|
||||
|
||||
List<String> fields = null;
|
||||
ObjectFloatHashMap<String> boosts = null;
|
||||
float tieBreaker = 0.0f;
|
||||
boolean useDisMax = true;
|
||||
/** To limit effort spent determinizing regexp queries. */
|
||||
private int maxDeterminizedStates;
|
||||
|
||||
public QueryParserSettings(String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
public String queryString() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
public void queryString(String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
public String defaultField() {
|
||||
return defaultField;
|
||||
}
|
||||
|
@ -87,12 +95,12 @@ public class QueryParserSettings {
|
|||
this.defaultField = defaultField;
|
||||
}
|
||||
|
||||
public float boost() {
|
||||
return boost;
|
||||
public Map<String, Float> fieldsAndWeights() {
|
||||
return fieldsAndWeights;
|
||||
}
|
||||
|
||||
public void boost(float boost) {
|
||||
this.boost = boost;
|
||||
public void fieldsAndWeights(Map<String, Float> fieldsAndWeights) {
|
||||
this.fieldsAndWeights = fieldsAndWeights;
|
||||
}
|
||||
|
||||
public QueryParser.Operator defaultOperator() {
|
||||
|
@ -175,44 +183,40 @@ public class QueryParserSettings {
|
|||
this.fuzzyRewriteMethod = fuzzyRewriteMethod;
|
||||
}
|
||||
|
||||
public boolean escape() {
|
||||
return escape;
|
||||
public void defaultAnalyzer(Analyzer analyzer) {
|
||||
this.analyzer = analyzer;
|
||||
this.forceAnalyzer = false;
|
||||
}
|
||||
|
||||
public void escape(boolean escape) {
|
||||
this.escape = escape;
|
||||
public void forceAnalyzer(Analyzer analyzer) {
|
||||
this.analyzer = analyzer;
|
||||
this.forceAnalyzer = true;
|
||||
}
|
||||
|
||||
public Analyzer defaultAnalyzer() {
|
||||
return defaultAnalyzer;
|
||||
public Analyzer analyzer() {
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
public void defaultAnalyzer(Analyzer defaultAnalyzer) {
|
||||
this.defaultAnalyzer = defaultAnalyzer;
|
||||
public boolean forceAnalyzer() {
|
||||
return forceAnalyzer;
|
||||
}
|
||||
|
||||
public Analyzer defaultQuoteAnalyzer() {
|
||||
return defaultQuoteAnalyzer;
|
||||
public void defaultQuoteAnalyzer(Analyzer quoteAnalyzer) {
|
||||
this.quoteAnalyzer = quoteAnalyzer;
|
||||
this.forceQuoteAnalyzer = false;
|
||||
}
|
||||
|
||||
public void defaultQuoteAnalyzer(Analyzer defaultAnalyzer) {
|
||||
this.defaultQuoteAnalyzer = defaultAnalyzer;
|
||||
public void forceQuoteAnalyzer(Analyzer quoteAnalyzer) {
|
||||
this.quoteAnalyzer = quoteAnalyzer;
|
||||
this.forceQuoteAnalyzer = true;
|
||||
}
|
||||
|
||||
public Analyzer forcedAnalyzer() {
|
||||
return forcedAnalyzer;
|
||||
public Analyzer quoteAnalyzer() {
|
||||
return quoteAnalyzer;
|
||||
}
|
||||
|
||||
public void forcedAnalyzer(Analyzer forcedAnalyzer) {
|
||||
this.forcedAnalyzer = forcedAnalyzer;
|
||||
}
|
||||
|
||||
public Analyzer forcedQuoteAnalyzer() {
|
||||
return forcedQuoteAnalyzer;
|
||||
}
|
||||
|
||||
public void forcedQuoteAnalyzer(Analyzer forcedAnalyzer) {
|
||||
this.forcedQuoteAnalyzer = forcedAnalyzer;
|
||||
public boolean forceQuoteAnalyzer() {
|
||||
return forceQuoteAnalyzer;
|
||||
}
|
||||
|
||||
public boolean analyzeWildcard() {
|
||||
|
@ -231,14 +235,6 @@ public class QueryParserSettings {
|
|||
this.rewriteMethod = rewriteMethod;
|
||||
}
|
||||
|
||||
public String minimumShouldMatch() {
|
||||
return this.minimumShouldMatch;
|
||||
}
|
||||
|
||||
public void minimumShouldMatch(String minimumShouldMatch) {
|
||||
this.minimumShouldMatch = minimumShouldMatch;
|
||||
}
|
||||
|
||||
public void quoteFieldSuffix(String quoteFieldSuffix) {
|
||||
this.quoteFieldSuffix = quoteFieldSuffix;
|
||||
}
|
||||
|
@ -255,22 +251,6 @@ public class QueryParserSettings {
|
|||
return this.lenient;
|
||||
}
|
||||
|
||||
public List<String> fields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void fields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public ObjectFloatHashMap<String> boosts() {
|
||||
return boosts;
|
||||
}
|
||||
|
||||
public void boosts(ObjectFloatHashMap<String> boosts) {
|
||||
this.boosts = boosts;
|
||||
}
|
||||
|
||||
public float tieBreaker() {
|
||||
return tieBreaker;
|
||||
}
|
||||
|
@ -303,97 +283,11 @@ public class QueryParserSettings {
|
|||
return this.timeZone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
QueryParserSettings that = (QueryParserSettings) o;
|
||||
|
||||
if (autoGeneratePhraseQueries != that.autoGeneratePhraseQueries()) return false;
|
||||
if (maxDeterminizedStates != that.maxDeterminizedStates()) return false;
|
||||
if (allowLeadingWildcard != that.allowLeadingWildcard) return false;
|
||||
if (Float.compare(that.boost, boost) != 0) return false;
|
||||
if (enablePositionIncrements != that.enablePositionIncrements) return false;
|
||||
if (escape != that.escape) return false;
|
||||
if (analyzeWildcard != that.analyzeWildcard) return false;
|
||||
if (fuzziness != null ? fuzziness.equals(that.fuzziness) == false : fuzziness != null) return false;
|
||||
if (fuzzyPrefixLength != that.fuzzyPrefixLength) return false;
|
||||
if (fuzzyMaxExpansions != that.fuzzyMaxExpansions) return false;
|
||||
if (fuzzyRewriteMethod != null ? !fuzzyRewriteMethod.equals(that.fuzzyRewriteMethod) : that.fuzzyRewriteMethod != null)
|
||||
return false;
|
||||
if (lowercaseExpandedTerms != that.lowercaseExpandedTerms) return false;
|
||||
if (phraseSlop != that.phraseSlop) return false;
|
||||
if (defaultAnalyzer != null ? !defaultAnalyzer.equals(that.defaultAnalyzer) : that.defaultAnalyzer != null)
|
||||
return false;
|
||||
if (defaultQuoteAnalyzer != null ? !defaultQuoteAnalyzer.equals(that.defaultQuoteAnalyzer) : that.defaultQuoteAnalyzer != null)
|
||||
return false;
|
||||
if (forcedAnalyzer != null ? !forcedAnalyzer.equals(that.forcedAnalyzer) : that.forcedAnalyzer != null)
|
||||
return false;
|
||||
if (forcedQuoteAnalyzer != null ? !forcedQuoteAnalyzer.equals(that.forcedQuoteAnalyzer) : that.forcedQuoteAnalyzer != null)
|
||||
return false;
|
||||
if (defaultField != null ? !defaultField.equals(that.defaultField) : that.defaultField != null) return false;
|
||||
if (defaultOperator != that.defaultOperator) return false;
|
||||
if (queryString != null ? !queryString.equals(that.queryString) : that.queryString != null) return false;
|
||||
if (rewriteMethod != null ? !rewriteMethod.equals(that.rewriteMethod) : that.rewriteMethod != null)
|
||||
return false;
|
||||
if (minimumShouldMatch != null ? !minimumShouldMatch.equals(that.minimumShouldMatch) : that.minimumShouldMatch != null)
|
||||
return false;
|
||||
if (quoteFieldSuffix != null ? !quoteFieldSuffix.equals(that.quoteFieldSuffix) : that.quoteFieldSuffix != null)
|
||||
return false;
|
||||
if (lenient != that.lenient) {
|
||||
return false;
|
||||
}
|
||||
if (locale != null ? !locale.equals(that.locale) : that.locale != null) {
|
||||
return false;
|
||||
}
|
||||
if (timeZone != null ? !timeZone.equals(that.timeZone) : that.timeZone != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Float.compare(that.tieBreaker, tieBreaker) != 0) return false;
|
||||
if (useDisMax != that.useDisMax) return false;
|
||||
if (boosts != null ? !boosts.equals(that.boosts) : that.boosts != null) return false;
|
||||
if (fields != null ? !fields.equals(that.fields) : that.fields != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = queryString != null ? queryString.hashCode() : 0;
|
||||
result = 31 * result + (defaultField != null ? defaultField.hashCode() : 0);
|
||||
result = 31 * result + (boost != +0.0f ? Float.floatToIntBits(boost) : 0);
|
||||
result = 31 * result + (defaultOperator != null ? defaultOperator.hashCode() : 0);
|
||||
result = 31 * result + (autoGeneratePhraseQueries ? 1 : 0);
|
||||
result = 31 * result + maxDeterminizedStates;
|
||||
result = 31 * result + (allowLeadingWildcard ? 1 : 0);
|
||||
result = 31 * result + (lowercaseExpandedTerms ? 1 : 0);
|
||||
result = 31 * result + (enablePositionIncrements ? 1 : 0);
|
||||
result = 31 * result + phraseSlop;
|
||||
result = 31 * result + (fuzziness.hashCode());
|
||||
result = 31 * result + fuzzyPrefixLength;
|
||||
result = 31 * result + (escape ? 1 : 0);
|
||||
result = 31 * result + (defaultAnalyzer != null ? defaultAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (defaultQuoteAnalyzer != null ? defaultQuoteAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (forcedAnalyzer != null ? forcedAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (forcedQuoteAnalyzer != null ? forcedQuoteAnalyzer.hashCode() : 0);
|
||||
result = 31 * result + (analyzeWildcard ? 1 : 0);
|
||||
|
||||
result = 31 * result + (fields != null ? fields.hashCode() : 0);
|
||||
result = 31 * result + (boosts != null ? boosts.hashCode() : 0);
|
||||
result = 31 * result + (tieBreaker != +0.0f ? Float.floatToIntBits(tieBreaker) : 0);
|
||||
result = 31 * result + (useDisMax ? 1 : 0);
|
||||
result = 31 * result + (locale != null ? locale.hashCode() : 0);
|
||||
result = 31 * result + (timeZone != null ? timeZone.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setFuzziness(Fuzziness fuzziness) {
|
||||
public void fuzziness(Fuzziness fuzziness) {
|
||||
this.fuzziness = fuzziness;
|
||||
}
|
||||
|
||||
public Fuzziness getFuzziness() {
|
||||
public Fuzziness fuzziness() {
|
||||
return fuzziness;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
|
||||
public static final String DEFAULT_FIELD = "index.query.default_field";
|
||||
public static final String QUERY_STRING_LENIENT = "index.query_string.lenient";
|
||||
public static final String QUERY_STRING_ANALYZE_WILDCARD = "indices.query.query_string.analyze_wildcard";
|
||||
public static final String QUERY_STRING_ALLOW_LEADING_WILDCARD = "indices.query.query_string.allowLeadingWildcard";
|
||||
public static final String PARSE_STRICT = "index.query.parse.strict";
|
||||
public static final String ALLOW_UNMAPPED = "index.query.parse.allow_unmapped_fields";
|
||||
private final InnerHitsQueryParserHelper innerHitsQueryParserHelper;
|
||||
|
@ -89,15 +91,17 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
|
||||
private final IndicesQueriesRegistry indicesQueriesRegistry;
|
||||
|
||||
private String defaultField;
|
||||
private boolean queryStringLenient;
|
||||
private final String defaultField;
|
||||
private final boolean queryStringLenient;
|
||||
private final boolean queryStringAnalyzeWildcard;
|
||||
private final boolean queryStringAllowLeadingWildcard;
|
||||
private final ParseFieldMatcher parseFieldMatcher;
|
||||
private final boolean defaultAllowUnmappedFields;
|
||||
|
||||
private TermsLookupFetchService termsLookupFetchService;
|
||||
|
||||
@Inject
|
||||
public IndexQueryParserService(Index index, @IndexSettings Settings indexSettings,
|
||||
public IndexQueryParserService(Index index, @IndexSettings Settings indexSettings, Settings settings,
|
||||
IndicesQueriesRegistry indicesQueriesRegistry,
|
||||
ScriptService scriptService, AnalysisService analysisService,
|
||||
MapperService mapperService, IndexCache indexCache, IndexFieldDataService fieldDataService,
|
||||
|
@ -118,6 +122,8 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
|
||||
this.defaultField = indexSettings.get(DEFAULT_FIELD, AllFieldMapper.NAME);
|
||||
this.queryStringLenient = indexSettings.getAsBoolean(QUERY_STRING_LENIENT, false);
|
||||
this.queryStringAnalyzeWildcard = settings.getAsBoolean(QUERY_STRING_ANALYZE_WILDCARD, false);
|
||||
this.queryStringAllowLeadingWildcard = settings.getAsBoolean(QUERY_STRING_ALLOW_LEADING_WILDCARD, true);
|
||||
this.parseFieldMatcher = new ParseFieldMatcher(indexSettings);
|
||||
this.defaultAllowUnmappedFields = indexSettings.getAsBoolean(ALLOW_UNMAPPED, true);
|
||||
this.indicesQueriesRegistry = indicesQueriesRegistry;
|
||||
|
@ -137,6 +143,14 @@ public class IndexQueryParserService extends AbstractIndexComponent {
|
|||
return this.defaultField;
|
||||
}
|
||||
|
||||
public boolean queryStringAnalyzeWildcard() {
|
||||
return this.queryStringAnalyzeWildcard;
|
||||
}
|
||||
|
||||
public boolean queryStringAllowLeadingWildcard() {
|
||||
return this.queryStringAllowLeadingWildcard;
|
||||
}
|
||||
|
||||
public boolean queryStringLenient() {
|
||||
return this.queryStringLenient;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -34,7 +35,7 @@ public enum Operator implements Writeable<Operator> {
|
|||
|
||||
private static final Operator PROTOTYPE = OR;
|
||||
|
||||
private Operator(int ordinal) {
|
||||
Operator(int ordinal) {
|
||||
this.ordinal = ordinal;
|
||||
}
|
||||
|
||||
|
@ -49,6 +50,17 @@ public enum Operator implements Writeable<Operator> {
|
|||
}
|
||||
}
|
||||
|
||||
public QueryParser.Operator toQueryParserOperator() {
|
||||
switch (this) {
|
||||
case OR:
|
||||
return QueryParser.Operator.OR;
|
||||
case AND:
|
||||
return QueryParser.Operator.AND;
|
||||
default:
|
||||
throw Operator.newOperatorException(this.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operator readFrom(StreamInput in) throws IOException {
|
||||
int ord = in.readVInt();
|
||||
|
|
|
@ -162,6 +162,14 @@ public class QueryShardContext {
|
|||
return indexQueryParser.queryStringLenient();
|
||||
}
|
||||
|
||||
public boolean queryStringAnalyzeWildcard() {
|
||||
return indexQueryParser.queryStringAnalyzeWildcard();
|
||||
}
|
||||
|
||||
public boolean queryStringAllowLeadingWildcard() {
|
||||
return indexQueryParser.queryStringAllowLeadingWildcard();
|
||||
}
|
||||
|
||||
public MapperQueryParser queryParser(QueryParserSettings settings) {
|
||||
queryParser.reset(settings);
|
||||
return queryParser;
|
||||
|
|
|
@ -19,14 +19,27 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectFloatHashMap;
|
||||
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.FuzzyQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.automaton.Operations;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* A query that parses a query string and runs it. There are two modes that this operates. The first,
|
||||
|
@ -40,63 +53,89 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
|
||||
public static final String NAME = "query_string";
|
||||
|
||||
public static final boolean DEFAULT_AUTO_GENERATE_PHRASE_QUERIES = false;
|
||||
public static final int DEFAULT_MAX_DETERMINED_STATES = Operations.DEFAULT_MAX_DETERMINIZED_STATES;
|
||||
public static final boolean DEFAULT_LOWERCASE_EXPANDED_TERMS = true;
|
||||
public static final boolean DEFAULT_ENABLE_POSITION_INCREMENTS = true;
|
||||
public static final boolean DEFAULT_ESCAPE = false;
|
||||
public static final boolean DEFAULT_USE_DIS_MAX = true;
|
||||
public static final int DEFAULT_FUZZY_PREFIX_LENGTH = FuzzyQuery.defaultPrefixLength;
|
||||
public static final int DEFAULT_FUZZY_MAX_EXPANSIONS = FuzzyQuery.defaultMaxExpansions;
|
||||
public static final int DEFAULT_PHRASE_SLOP = 0;
|
||||
public static final float DEFAULT_TIE_BREAKER = 0.0f;
|
||||
public static final Fuzziness DEFAULT_FUZZINESS = Fuzziness.AUTO;
|
||||
public static final Operator DEFAULT_OPERATOR = Operator.OR;
|
||||
public static final Locale DEFAULT_LOCALE = Locale.ROOT;
|
||||
|
||||
static final QueryStringQueryBuilder PROTOTYPE = new QueryStringQueryBuilder(null);
|
||||
|
||||
private final String queryString;
|
||||
|
||||
private String defaultField;
|
||||
/**
|
||||
* Fields to query against. If left empty will query default field,
|
||||
* currently _ALL. Uses a TreeMap to hold the fields so boolean clauses are
|
||||
* always sorted in same order for generated Lucene query for easier
|
||||
* testing.
|
||||
*
|
||||
* Can be changed back to HashMap once https://issues.apache.org/jira/browse/LUCENE-6305 is fixed.
|
||||
*/
|
||||
private final Map<String, Float> fieldsAndWeights = new TreeMap<>();
|
||||
|
||||
private Operator defaultOperator;
|
||||
private Operator defaultOperator = DEFAULT_OPERATOR;
|
||||
|
||||
private String analyzer;
|
||||
private String quoteAnalyzer;
|
||||
|
||||
private String quoteFieldSuffix;
|
||||
|
||||
private Boolean autoGeneratePhraseQueries;
|
||||
private boolean autoGeneratePhraseQueries = DEFAULT_AUTO_GENERATE_PHRASE_QUERIES;
|
||||
|
||||
private Boolean allowLeadingWildcard;
|
||||
|
||||
private Boolean lowercaseExpandedTerms;
|
||||
|
||||
private Boolean enablePositionIncrements;
|
||||
|
||||
private Boolean analyzeWildcard;
|
||||
|
||||
private Locale locale;
|
||||
private boolean lowercaseExpandedTerms = DEFAULT_LOWERCASE_EXPANDED_TERMS;
|
||||
|
||||
private boolean enablePositionIncrements = DEFAULT_ENABLE_POSITION_INCREMENTS;
|
||||
|
||||
private Locale locale = DEFAULT_LOCALE;
|
||||
|
||||
private Fuzziness fuzziness = DEFAULT_FUZZINESS;
|
||||
|
||||
private int fuzzyPrefixLength = DEFAULT_FUZZY_PREFIX_LENGTH;
|
||||
|
||||
private int fuzzyMaxExpansions = DEFAULT_FUZZY_MAX_EXPANSIONS;
|
||||
|
||||
private String rewrite;
|
||||
|
||||
private Fuzziness fuzziness;
|
||||
private int fuzzyPrefixLength = -1;
|
||||
private int fuzzyMaxExpansions = -1;
|
||||
private String fuzzyRewrite;
|
||||
|
||||
private int phraseSlop = -1;
|
||||
private boolean escape = DEFAULT_ESCAPE;
|
||||
|
||||
private List<String> fields;
|
||||
private int phraseSlop = DEFAULT_PHRASE_SLOP;
|
||||
|
||||
private ObjectFloatHashMap<String> fieldsBoosts;
|
||||
private boolean useDisMax = DEFAULT_USE_DIS_MAX;
|
||||
|
||||
private Boolean useDisMax;
|
||||
|
||||
private float tieBreaker = -1;
|
||||
|
||||
private String rewrite = null;
|
||||
private float tieBreaker = DEFAULT_TIE_BREAKER;
|
||||
|
||||
private String minimumShouldMatch;
|
||||
|
||||
private Boolean lenient;
|
||||
|
||||
private String timeZone;
|
||||
|
||||
private Boolean escape;
|
||||
private DateTimeZone timeZone;
|
||||
|
||||
/** To limit effort spent determinizing regexp queries. */
|
||||
private Integer maxDeterminizedStates;
|
||||
|
||||
static final QueryStringQueryBuilder PROTOTYPE = new QueryStringQueryBuilder(null);
|
||||
private int maxDeterminizedStates = DEFAULT_MAX_DETERMINED_STATES;
|
||||
|
||||
public QueryStringQueryBuilder(String queryString) {
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
public String queryString() {
|
||||
return this.queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default field to run against when no prefix field is specified. Only relevant when
|
||||
* not explicitly adding fields the query string will run against.
|
||||
|
@ -106,14 +145,16 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public String defaultField() {
|
||||
return this.defaultField;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to run the query string against.
|
||||
* Adds a field to run the query string against. The field will be associated with the default boost of {@link AbstractQueryBuilder#DEFAULT_BOOST}.
|
||||
* Use {@link #field(String, float)} to set a specific boost for the field.
|
||||
*/
|
||||
public QueryStringQueryBuilder field(String field) {
|
||||
if (fields == null) {
|
||||
fields = new ArrayList<>();
|
||||
}
|
||||
fields.add(field);
|
||||
this.fieldsAndWeights.put(field, AbstractQueryBuilder.DEFAULT_BOOST);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -121,17 +162,23 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
* Adds a field to run the query string against with a specific boost.
|
||||
*/
|
||||
public QueryStringQueryBuilder field(String field, float boost) {
|
||||
if (fields == null) {
|
||||
fields = new ArrayList<>();
|
||||
}
|
||||
fields.add(field);
|
||||
if (fieldsBoosts == null) {
|
||||
fieldsBoosts = new ObjectFloatHashMap<>();
|
||||
}
|
||||
fieldsBoosts.put(field, boost);
|
||||
this.fieldsAndWeights.put(field, boost);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add several fields to run the query against with a specific boost.
|
||||
*/
|
||||
public QueryStringQueryBuilder fields(Map<String, Float> fields) {
|
||||
this.fieldsAndWeights.putAll(fields);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns the fields including their respective boosts to run the query against. */
|
||||
public Map<String, Float> fields() {
|
||||
return this.fieldsAndWeights;
|
||||
}
|
||||
|
||||
/**
|
||||
* When more than one field is used with the query string, should queries be combined using
|
||||
* dis max, or boolean query. Defaults to dis max (<tt>true</tt>).
|
||||
|
@ -141,6 +188,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean useDisMax() {
|
||||
return this.useDisMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* When more than one field is used with the query string, and combined queries are using
|
||||
* dis max, control the tie breaker for it.
|
||||
|
@ -150,6 +201,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public float tieBreaker() {
|
||||
return this.tieBreaker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the boolean operator of the query parser used to parse the query string.
|
||||
* <p/>
|
||||
|
@ -161,10 +216,14 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
* above mentioned query is parsed as <code>capital AND of AND Hungary</code>
|
||||
*/
|
||||
public QueryStringQueryBuilder defaultOperator(Operator defaultOperator) {
|
||||
this.defaultOperator = defaultOperator;
|
||||
this.defaultOperator = defaultOperator == null ? DEFAULT_OPERATOR : defaultOperator;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Operator defaultOperator() {
|
||||
return this.defaultOperator;
|
||||
}
|
||||
|
||||
/**
|
||||
* The optional analyzer used to analyze the query string. Note, if a field has search analyzer
|
||||
* defined for it, then it will be used automatically. Defaults to the smart search analyzer.
|
||||
|
@ -178,12 +237,11 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
* The optional analyzer used to analyze the query string for phrase searches. Note, if a field has search (quote) analyzer
|
||||
* defined for it, then it will be used automatically. Defaults to the smart search analyzer.
|
||||
*/
|
||||
public QueryStringQueryBuilder quoteAnalyzer(String analyzer) {
|
||||
this.quoteAnalyzer = analyzer;
|
||||
public QueryStringQueryBuilder quoteAnalyzer(String quoteAnalyzer) {
|
||||
this.quoteAnalyzer = quoteAnalyzer;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set to true if phrase queries will be automatically generated
|
||||
* when the analyzer returns more than one term from whitespace
|
||||
|
@ -198,6 +256,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean autoGeneratePhraseQueries() {
|
||||
return this.autoGeneratePhraseQueries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protects against too-difficult regular expression queries.
|
||||
*/
|
||||
|
@ -206,14 +268,22 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public int maxDeterminizedStates() {
|
||||
return this.maxDeterminizedStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should leading wildcards be allowed or not. Defaults to <tt>true</tt>.
|
||||
*/
|
||||
public QueryStringQueryBuilder allowLeadingWildcard(boolean allowLeadingWildcard) {
|
||||
public QueryStringQueryBuilder allowLeadingWildcard(Boolean allowLeadingWildcard) {
|
||||
this.allowLeadingWildcard = allowLeadingWildcard;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean allowLeadingWildcard() {
|
||||
return this.allowLeadingWildcard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
|
||||
* lower-cased or not. Default is <tt>true</tt>.
|
||||
|
@ -223,6 +293,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean lowercaseExpandedTerms() {
|
||||
return this.lowercaseExpandedTerms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to <tt>true</tt> to enable position increments in result query. Defaults to
|
||||
* <tt>true</tt>.
|
||||
|
@ -235,14 +309,22 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean enablePositionIncrements() {
|
||||
return this.enablePositionIncrements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the edit distance for fuzzy queries. Default is "AUTO".
|
||||
*/
|
||||
public QueryStringQueryBuilder fuzziness(Fuzziness fuzziness) {
|
||||
this.fuzziness = fuzziness;
|
||||
this.fuzziness = fuzziness == null ? DEFAULT_FUZZINESS : fuzziness;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Fuzziness fuzziness() {
|
||||
return this.fuzziness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum prefix length for fuzzy queries. Default is 1.
|
||||
*/
|
||||
|
@ -251,16 +333,28 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public int fuzzyPrefixLength() {
|
||||
return fuzzyPrefixLength;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder fuzzyMaxExpansions(int fuzzyMaxExpansions) {
|
||||
this.fuzzyMaxExpansions = fuzzyMaxExpansions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int fuzzyMaxExpansions() {
|
||||
return fuzzyMaxExpansions;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder fuzzyRewrite(String fuzzyRewrite) {
|
||||
this.fuzzyRewrite = fuzzyRewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String fuzzyRewrite() {
|
||||
return fuzzyRewrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default slop for phrases. If zero, then exact phrase matches
|
||||
* are required. Default value is zero.
|
||||
|
@ -270,24 +364,40 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public int phraseSlop() {
|
||||
return phraseSlop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to <tt>true</tt> to enable analysis on wildcard and prefix queries.
|
||||
*/
|
||||
public QueryStringQueryBuilder analyzeWildcard(boolean analyzeWildcard) {
|
||||
public QueryStringQueryBuilder analyzeWildcard(Boolean analyzeWildcard) {
|
||||
this.analyzeWildcard = analyzeWildcard;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean analyzeWildcard() {
|
||||
return this.analyzeWildcard;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder rewrite(String rewrite) {
|
||||
this.rewrite = rewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String rewrite() {
|
||||
return this.rewrite;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder minimumShouldMatch(String minimumShouldMatch) {
|
||||
this.minimumShouldMatch = minimumShouldMatch;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String minimumShouldMatch() {
|
||||
return this.minimumShouldMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional field name suffix to automatically try and add to the field searched when using quoted text.
|
||||
*/
|
||||
|
@ -296,6 +406,10 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public String quoteFieldSuffix() {
|
||||
return this.quoteFieldSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the query string parser to be lenient when parsing field values, defaults to the index
|
||||
* setting and if not set, defaults to false.
|
||||
|
@ -305,19 +419,40 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public Boolean lenient() {
|
||||
return this.lenient;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder locale(Locale locale) {
|
||||
this.locale = locale;
|
||||
this.locale = locale == null ? DEFAULT_LOCALE : locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Locale locale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of date field, we can adjust the from/to fields using a timezone
|
||||
*/
|
||||
public QueryStringQueryBuilder timeZone(String timeZone) {
|
||||
if (timeZone != null) {
|
||||
this.timeZone = DateTimeZone.forID(timeZone);
|
||||
} else {
|
||||
this.timeZone = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder timeZone(DateTimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DateTimeZone timeZone() {
|
||||
return this.timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to <tt>true</tt> to enable escaping of the query string
|
||||
*/
|
||||
|
@ -326,92 +461,65 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean escape() {
|
||||
return this.escape;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
builder.field("query", queryString);
|
||||
if (defaultField != null) {
|
||||
builder.field("default_field", defaultField);
|
||||
builder.field("query", this.queryString);
|
||||
if (this.defaultField != null) {
|
||||
builder.field("default_field", this.defaultField);
|
||||
}
|
||||
if (fields != null) {
|
||||
builder.startArray("fields");
|
||||
for (String field : fields) {
|
||||
if (fieldsBoosts != null && fieldsBoosts.containsKey(field)) {
|
||||
field += "^" + fieldsBoosts.get(field);
|
||||
}
|
||||
builder.value(field);
|
||||
}
|
||||
builder.endArray();
|
||||
builder.startArray("fields");
|
||||
for (Map.Entry<String, Float> fieldEntry : this.fieldsAndWeights.entrySet()) {
|
||||
builder.value(fieldEntry.getKey() + "^" + fieldEntry.getValue());
|
||||
}
|
||||
if (useDisMax != null) {
|
||||
builder.field("use_dis_max", useDisMax);
|
||||
builder.endArray();
|
||||
builder.field("use_dis_max", this.useDisMax);
|
||||
builder.field("tie_breaker", this.tieBreaker);
|
||||
builder.field("default_operator", this.defaultOperator.name().toLowerCase(Locale.ROOT));
|
||||
if (this.analyzer != null) {
|
||||
builder.field("analyzer", this.analyzer);
|
||||
}
|
||||
if (tieBreaker != -1) {
|
||||
builder.field("tie_breaker", tieBreaker);
|
||||
if (this.quoteAnalyzer != null) {
|
||||
builder.field("quote_analyzer", this.quoteAnalyzer);
|
||||
}
|
||||
if (defaultOperator != null) {
|
||||
builder.field("default_operator", defaultOperator.name().toLowerCase(Locale.ROOT));
|
||||
builder.field("auto_generate_phrase_queries", this.autoGeneratePhraseQueries);
|
||||
builder.field("max_determinized_states", this.maxDeterminizedStates);
|
||||
if (this.allowLeadingWildcard != null) {
|
||||
builder.field("allow_leading_wildcard", this.allowLeadingWildcard);
|
||||
}
|
||||
if (analyzer != null) {
|
||||
builder.field("analyzer", analyzer);
|
||||
builder.field("lowercase_expanded_terms", this.lowercaseExpandedTerms);
|
||||
builder.field("enable_position_increments", this.enablePositionIncrements);
|
||||
this.fuzziness.toXContent(builder, params);
|
||||
builder.field("fuzzy_prefix_length", this.fuzzyPrefixLength);
|
||||
builder.field("fuzzy_max_expansions", this.fuzzyMaxExpansions);
|
||||
if (this.fuzzyRewrite != null) {
|
||||
builder.field("fuzzy_rewrite", this.fuzzyRewrite);
|
||||
}
|
||||
if (quoteAnalyzer != null) {
|
||||
builder.field("quote_analyzer", quoteAnalyzer);
|
||||
builder.field("phrase_slop", this.phraseSlop);
|
||||
if (this.analyzeWildcard != null) {
|
||||
builder.field("analyze_wildcard", this.analyzeWildcard);
|
||||
}
|
||||
if (autoGeneratePhraseQueries != null) {
|
||||
builder.field("auto_generate_phrase_queries", autoGeneratePhraseQueries);
|
||||
if (this.rewrite != null) {
|
||||
builder.field("rewrite", this.rewrite);
|
||||
}
|
||||
if (maxDeterminizedStates != null) {
|
||||
builder.field("max_determinized_states", maxDeterminizedStates);
|
||||
if (this.minimumShouldMatch != null) {
|
||||
builder.field("minimum_should_match", this.minimumShouldMatch);
|
||||
}
|
||||
if (allowLeadingWildcard != null) {
|
||||
builder.field("allow_leading_wildcard", allowLeadingWildcard);
|
||||
if (this.quoteFieldSuffix != null) {
|
||||
builder.field("quote_field_suffix", this.quoteFieldSuffix);
|
||||
}
|
||||
if (lowercaseExpandedTerms != null) {
|
||||
builder.field("lowercase_expanded_terms", lowercaseExpandedTerms);
|
||||
if (this.lenient != null) {
|
||||
builder.field("lenient", this.lenient);
|
||||
}
|
||||
if (enablePositionIncrements != null) {
|
||||
builder.field("enable_position_increments", enablePositionIncrements);
|
||||
}
|
||||
if (fuzziness != null) {
|
||||
fuzziness.toXContent(builder, params);
|
||||
}
|
||||
if (fuzzyPrefixLength != -1) {
|
||||
builder.field("fuzzy_prefix_length", fuzzyPrefixLength);
|
||||
}
|
||||
if (fuzzyMaxExpansions != -1) {
|
||||
builder.field("fuzzy_max_expansions", fuzzyMaxExpansions);
|
||||
}
|
||||
if (fuzzyRewrite != null) {
|
||||
builder.field("fuzzy_rewrite", fuzzyRewrite);
|
||||
}
|
||||
if (phraseSlop != -1) {
|
||||
builder.field("phrase_slop", phraseSlop);
|
||||
}
|
||||
if (analyzeWildcard != null) {
|
||||
builder.field("analyze_wildcard", analyzeWildcard);
|
||||
}
|
||||
if (rewrite != null) {
|
||||
builder.field("rewrite", rewrite);
|
||||
}
|
||||
if (minimumShouldMatch != null) {
|
||||
builder.field("minimum_should_match", minimumShouldMatch);
|
||||
}
|
||||
if (quoteFieldSuffix != null) {
|
||||
builder.field("quote_field_suffix", quoteFieldSuffix);
|
||||
}
|
||||
if (lenient != null) {
|
||||
builder.field("lenient", lenient);
|
||||
}
|
||||
if (locale != null) {
|
||||
builder.field("locale", locale.toString());
|
||||
}
|
||||
if (timeZone != null) {
|
||||
builder.field("time_zone", timeZone);
|
||||
}
|
||||
if (escape != null) {
|
||||
builder.field("escape", escape);
|
||||
builder.field("locale", this.locale.toLanguageTag());
|
||||
if (this.timeZone != null) {
|
||||
builder.field("time_zone", this.timeZone.getID());
|
||||
}
|
||||
builder.field("escape", this.escape);
|
||||
printBoostAndQueryName(builder);
|
||||
builder.endObject();
|
||||
}
|
||||
|
@ -420,4 +528,217 @@ public class QueryStringQueryBuilder extends AbstractQueryBuilder<QueryStringQue
|
|||
public String getWriteableName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryValidationException validate() {
|
||||
QueryValidationException validationException = null;
|
||||
if (queryString == null) {
|
||||
validationException = addValidationError("query text missing", null);
|
||||
}
|
||||
return validationException;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryStringQueryBuilder doReadFrom(StreamInput in) throws IOException {
|
||||
QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(in.readString());
|
||||
queryStringQueryBuilder.defaultField = in.readOptionalString();
|
||||
int size = in.readVInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
queryStringQueryBuilder.fieldsAndWeights.put(in.readString(), in.readFloat());
|
||||
}
|
||||
queryStringQueryBuilder.defaultOperator = Operator.readOperatorFrom(in);
|
||||
queryStringQueryBuilder.analyzer = in.readOptionalString();
|
||||
queryStringQueryBuilder.quoteAnalyzer = in.readOptionalString();
|
||||
queryStringQueryBuilder.quoteFieldSuffix = in.readOptionalString();
|
||||
queryStringQueryBuilder.autoGeneratePhraseQueries = in.readBoolean();
|
||||
queryStringQueryBuilder.allowLeadingWildcard = in.readOptionalBoolean();
|
||||
queryStringQueryBuilder.analyzeWildcard = in.readOptionalBoolean();
|
||||
queryStringQueryBuilder.lowercaseExpandedTerms = in.readBoolean();
|
||||
queryStringQueryBuilder.enablePositionIncrements = in.readBoolean();
|
||||
queryStringQueryBuilder.locale = Locale.forLanguageTag(in.readString());
|
||||
queryStringQueryBuilder.fuzziness = Fuzziness.readFuzzinessFrom(in);
|
||||
queryStringQueryBuilder.fuzzyPrefixLength = in.readVInt();
|
||||
queryStringQueryBuilder.fuzzyMaxExpansions = in.readVInt();
|
||||
queryStringQueryBuilder.fuzzyRewrite = in.readOptionalString();
|
||||
queryStringQueryBuilder.phraseSlop = in.readVInt();
|
||||
queryStringQueryBuilder.useDisMax = in.readBoolean();
|
||||
queryStringQueryBuilder.tieBreaker = in.readFloat();
|
||||
queryStringQueryBuilder.rewrite = in.readOptionalString();
|
||||
queryStringQueryBuilder.minimumShouldMatch = in.readOptionalString();
|
||||
queryStringQueryBuilder.lenient = in.readOptionalBoolean();
|
||||
if (in.readBoolean()) {
|
||||
queryStringQueryBuilder.timeZone = DateTimeZone.forID(in.readString());
|
||||
}
|
||||
queryStringQueryBuilder.escape = in.readBoolean();
|
||||
queryStringQueryBuilder.maxDeterminizedStates = in.readVInt();
|
||||
return queryStringQueryBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(this.queryString);
|
||||
out.writeOptionalString(this.defaultField);
|
||||
out.writeVInt(this.fieldsAndWeights.size());
|
||||
for (Map.Entry<String, Float> fieldsEntry : this.fieldsAndWeights.entrySet()) {
|
||||
out.writeString(fieldsEntry.getKey());
|
||||
out.writeFloat(fieldsEntry.getValue());
|
||||
}
|
||||
this.defaultOperator.writeTo(out);
|
||||
out.writeOptionalString(this.analyzer);
|
||||
out.writeOptionalString(this.quoteAnalyzer);
|
||||
out.writeOptionalString(this.quoteFieldSuffix);
|
||||
out.writeBoolean(this.autoGeneratePhraseQueries);
|
||||
out.writeOptionalBoolean(this.allowLeadingWildcard);
|
||||
out.writeOptionalBoolean(this.analyzeWildcard);
|
||||
out.writeBoolean(this.lowercaseExpandedTerms);
|
||||
out.writeBoolean(this.enablePositionIncrements);
|
||||
out.writeString(this.locale.toLanguageTag());
|
||||
this.fuzziness.writeTo(out);
|
||||
out.writeVInt(this.fuzzyPrefixLength);
|
||||
out.writeVInt(this.fuzzyMaxExpansions);
|
||||
out.writeOptionalString(this.fuzzyRewrite);
|
||||
out.writeVInt(this.phraseSlop);
|
||||
out.writeBoolean(this.useDisMax);
|
||||
out.writeFloat(this.tieBreaker);
|
||||
out.writeOptionalString(this.rewrite);
|
||||
out.writeOptionalString(this.minimumShouldMatch);
|
||||
out.writeOptionalBoolean(this.lenient);
|
||||
if (this.timeZone == null) {
|
||||
out.writeBoolean(false);
|
||||
} else {
|
||||
out.writeBoolean(true);
|
||||
out.writeString(this.timeZone.getID());
|
||||
}
|
||||
out.writeBoolean(this.escape);
|
||||
out.writeVInt(this.maxDeterminizedStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doEquals(QueryStringQueryBuilder other) {
|
||||
return Objects.equals(queryString, other.queryString) &&
|
||||
Objects.equals(defaultField, other.defaultField) &&
|
||||
Objects.equals(fieldsAndWeights, other.fieldsAndWeights) &&
|
||||
Objects.equals(defaultOperator, other.defaultOperator) &&
|
||||
Objects.equals(analyzer, other.analyzer) &&
|
||||
Objects.equals(quoteAnalyzer, other.quoteAnalyzer) &&
|
||||
Objects.equals(quoteFieldSuffix, other.quoteFieldSuffix) &&
|
||||
Objects.equals(autoGeneratePhraseQueries, other.autoGeneratePhraseQueries) &&
|
||||
Objects.equals(allowLeadingWildcard, other.allowLeadingWildcard) &&
|
||||
Objects.equals(lowercaseExpandedTerms, other.lowercaseExpandedTerms) &&
|
||||
Objects.equals(enablePositionIncrements, other.enablePositionIncrements) &&
|
||||
Objects.equals(analyzeWildcard, other.analyzeWildcard) &&
|
||||
Objects.equals(locale.toLanguageTag(), other.locale.toLanguageTag()) &&
|
||||
Objects.equals(fuzziness, other.fuzziness) &&
|
||||
Objects.equals(fuzzyPrefixLength, other.fuzzyPrefixLength) &&
|
||||
Objects.equals(fuzzyMaxExpansions, other.fuzzyMaxExpansions) &&
|
||||
Objects.equals(fuzzyRewrite, other.fuzzyRewrite) &&
|
||||
Objects.equals(phraseSlop, other.phraseSlop) &&
|
||||
Objects.equals(useDisMax, other.useDisMax) &&
|
||||
Objects.equals(tieBreaker, other.tieBreaker) &&
|
||||
Objects.equals(rewrite, other.rewrite) &&
|
||||
Objects.equals(minimumShouldMatch, other.minimumShouldMatch) &&
|
||||
Objects.equals(lenient, other.lenient) &&
|
||||
timeZone == null ? other.timeZone == null : other.timeZone != null && Objects.equals(timeZone.getID(), other.timeZone.getID()) &&
|
||||
Objects.equals(escape, other.escape) &&
|
||||
Objects.equals(maxDeterminizedStates, other.maxDeterminizedStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(queryString, defaultField, fieldsAndWeights, defaultOperator, analyzer, quoteAnalyzer,
|
||||
quoteFieldSuffix, autoGeneratePhraseQueries, allowLeadingWildcard, lowercaseExpandedTerms,
|
||||
enablePositionIncrements, analyzeWildcard, locale.toLanguageTag(), fuzziness, fuzzyPrefixLength,
|
||||
fuzzyMaxExpansions, fuzzyRewrite, phraseSlop, useDisMax, tieBreaker, rewrite, minimumShouldMatch, lenient,
|
||||
timeZone == null ? 0 : timeZone.getID(), escape, maxDeterminizedStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
//TODO would be nice to have all the settings in one place: some change though at query execution time
|
||||
//e.g. field names get expanded to concrete names, defaults get resolved sometimes to settings values etc.
|
||||
QueryParserSettings qpSettings;
|
||||
if (this.escape) {
|
||||
qpSettings = new QueryParserSettings(org.apache.lucene.queryparser.classic.QueryParser.escape(this.queryString));
|
||||
} else {
|
||||
qpSettings = new QueryParserSettings(this.queryString);
|
||||
}
|
||||
qpSettings.defaultField(this.defaultField == null ? context.defaultField() : this.defaultField);
|
||||
Map<String, Float> resolvedFields = new TreeMap<>();
|
||||
for (Map.Entry<String, Float> fieldsEntry : fieldsAndWeights.entrySet()) {
|
||||
String fieldName = fieldsEntry.getKey();
|
||||
Float weight = fieldsEntry.getValue();
|
||||
if (Regex.isSimpleMatchPattern(fieldName)) {
|
||||
for (String resolvedFieldName : context.mapperService().simpleMatchToIndexNames(fieldName)) {
|
||||
resolvedFields.put(resolvedFieldName, weight);
|
||||
}
|
||||
} else {
|
||||
resolvedFields.put(fieldName, weight);
|
||||
}
|
||||
}
|
||||
qpSettings.fieldsAndWeights(resolvedFields);
|
||||
qpSettings.defaultOperator(defaultOperator.toQueryParserOperator());
|
||||
|
||||
if (analyzer == null) {
|
||||
qpSettings.defaultAnalyzer(context.mapperService().searchAnalyzer());
|
||||
} else {
|
||||
NamedAnalyzer namedAnalyzer = context.analysisService().analyzer(analyzer);
|
||||
if (namedAnalyzer == null) {
|
||||
throw new QueryShardException(context, "[query_string] analyzer [" + analyzer + "] not found");
|
||||
}
|
||||
qpSettings.forceAnalyzer(namedAnalyzer);
|
||||
}
|
||||
if (quoteAnalyzer != null) {
|
||||
NamedAnalyzer namedAnalyzer = context.analysisService().analyzer(quoteAnalyzer);
|
||||
if (namedAnalyzer == null) {
|
||||
throw new QueryShardException(context, "[query_string] quote_analyzer [" + quoteAnalyzer + "] not found");
|
||||
}
|
||||
qpSettings.forceQuoteAnalyzer(namedAnalyzer);
|
||||
} else if (analyzer != null) {
|
||||
qpSettings.forceQuoteAnalyzer(qpSettings.analyzer());
|
||||
} else {
|
||||
qpSettings.defaultQuoteAnalyzer(context.mapperService().searchQuoteAnalyzer());
|
||||
}
|
||||
|
||||
qpSettings.quoteFieldSuffix(quoteFieldSuffix);
|
||||
qpSettings.autoGeneratePhraseQueries(autoGeneratePhraseQueries);
|
||||
qpSettings.allowLeadingWildcard(allowLeadingWildcard == null ? context.queryStringAllowLeadingWildcard() : allowLeadingWildcard);
|
||||
qpSettings.analyzeWildcard(analyzeWildcard == null ? context.queryStringAnalyzeWildcard() : analyzeWildcard);
|
||||
qpSettings.lowercaseExpandedTerms(lowercaseExpandedTerms);
|
||||
qpSettings.enablePositionIncrements(enablePositionIncrements);
|
||||
qpSettings.locale(locale);
|
||||
qpSettings.fuzziness(fuzziness);
|
||||
qpSettings.fuzzyPrefixLength(fuzzyPrefixLength);
|
||||
qpSettings.fuzzyMaxExpansions(fuzzyMaxExpansions);
|
||||
qpSettings.fuzzyRewriteMethod(QueryParsers.parseRewriteMethod(context.parseFieldMatcher(), this.fuzzyRewrite));
|
||||
qpSettings.phraseSlop(phraseSlop);
|
||||
qpSettings.useDisMax(useDisMax);
|
||||
qpSettings.tieBreaker(tieBreaker);
|
||||
qpSettings.rewriteMethod(QueryParsers.parseRewriteMethod(context.parseFieldMatcher(), this.rewrite));
|
||||
qpSettings.lenient(lenient == null ? context.queryStringLenient() : lenient);
|
||||
qpSettings.timeZone(timeZone);
|
||||
qpSettings.maxDeterminizedStates(maxDeterminizedStates);
|
||||
|
||||
MapperQueryParser queryParser = context.queryParser(qpSettings);
|
||||
Query query;
|
||||
try {
|
||||
query = queryParser.parse(queryString);
|
||||
} catch (org.apache.lucene.queryparser.classic.ParseException e) {
|
||||
throw new QueryShardException(context, "Failed to parse query [" + this.queryString + "]", e);
|
||||
}
|
||||
|
||||
if (query == null) {
|
||||
return null;
|
||||
}
|
||||
query = Queries.fixNegativeQueryIfNeeded(query);
|
||||
if (query instanceof BooleanQuery) {
|
||||
query = Queries.applyMinimumShouldMatch((BooleanQuery) query, this.minimumShouldMatch());
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFinalBoost(Query query) {
|
||||
//we need to preserve the boost that came out of the parsing phase
|
||||
query.setBoost(query.getBoost() * boost);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,44 +19,26 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectFloatHashMap;
|
||||
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.Query;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.util.LocaleUtils;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.lucene.search.Queries.fixNegativeQueryIfNeeded;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parser for query_string query
|
||||
*/
|
||||
public class QueryStringQueryParser extends BaseQueryParserTemp {
|
||||
public class QueryStringQueryParser extends BaseQueryParser {
|
||||
|
||||
private static final ParseField FUZZINESS = Fuzziness.FIELD.withDeprecation("fuzzy_min_sim");
|
||||
|
||||
private final boolean defaultAnalyzeWildcard;
|
||||
private final boolean defaultAllowLeadingWildcard;
|
||||
|
||||
@Inject
|
||||
public QueryStringQueryParser(Settings settings) {
|
||||
this.defaultAnalyzeWildcard = settings.getAsBoolean("indices.query.query_string.analyze_wildcard", QueryParserSettings.DEFAULT_ANALYZE_WILDCARD);
|
||||
this.defaultAllowLeadingWildcard = settings.getAsBoolean("indices.query.query_string.allowLeadingWildcard", QueryParserSettings.DEFAULT_ALLOW_LEADING_WILDCARD);
|
||||
public QueryStringQueryParser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,20 +47,38 @@ public class QueryStringQueryParser extends BaseQueryParserTemp {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryShardContext context) throws IOException, QueryParsingException {
|
||||
QueryParseContext parseContext = context.parseContext();
|
||||
public QueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
|
||||
String queryName = null;
|
||||
QueryParserSettings qpSettings = new QueryParserSettings();
|
||||
qpSettings.defaultField(context.defaultField());
|
||||
qpSettings.lenient(context.queryStringLenient());
|
||||
qpSettings.analyzeWildcard(defaultAnalyzeWildcard);
|
||||
qpSettings.allowLeadingWildcard(defaultAllowLeadingWildcard);
|
||||
qpSettings.locale(Locale.ROOT);
|
||||
|
||||
String currentFieldName = null;
|
||||
XContentParser.Token token;
|
||||
String queryString = null;
|
||||
String defaultField = null;
|
||||
String analyzer = null;
|
||||
String quoteAnalyzer = null;
|
||||
String queryName = null;
|
||||
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
|
||||
boolean autoGeneratePhraseQueries = QueryStringQueryBuilder.DEFAULT_AUTO_GENERATE_PHRASE_QUERIES;
|
||||
int maxDeterminizedStates = QueryStringQueryBuilder.DEFAULT_MAX_DETERMINED_STATES;
|
||||
boolean lowercaseExpandedTerms = QueryStringQueryBuilder.DEFAULT_LOWERCASE_EXPANDED_TERMS;
|
||||
boolean enablePositionIncrements = QueryStringQueryBuilder.DEFAULT_ENABLE_POSITION_INCREMENTS;
|
||||
boolean escape = QueryStringQueryBuilder.DEFAULT_ESCAPE;
|
||||
boolean useDisMax = QueryStringQueryBuilder.DEFAULT_USE_DIS_MAX;
|
||||
int fuzzyPrefixLength = QueryStringQueryBuilder.DEFAULT_FUZZY_PREFIX_LENGTH;
|
||||
int fuzzyMaxExpansions = QueryStringQueryBuilder.DEFAULT_FUZZY_MAX_EXPANSIONS;
|
||||
int phraseSlop = QueryStringQueryBuilder.DEFAULT_PHRASE_SLOP;
|
||||
float tieBreaker = QueryStringQueryBuilder.DEFAULT_TIE_BREAKER;
|
||||
Boolean analyzeWildcard = null;
|
||||
Boolean allowLeadingWildcard = null;
|
||||
String minimumShouldMatch = null;
|
||||
String quoteFieldSuffix = null;
|
||||
Boolean lenient = null;
|
||||
Operator defaultOperator = QueryStringQueryBuilder.DEFAULT_OPERATOR;
|
||||
String timeZone = null;
|
||||
Locale locale = QueryStringQueryBuilder.DEFAULT_LOCALE;
|
||||
Fuzziness fuzziness = QueryStringQueryBuilder.DEFAULT_FUZZINESS;
|
||||
String fuzzyRewrite = null;
|
||||
String rewrite = null;
|
||||
Map<String, Float> fieldsAndWeights = new HashMap<>();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
|
@ -86,7 +86,7 @@ public class QueryStringQueryParser extends BaseQueryParserTemp {
|
|||
if ("fields".equals(currentFieldName)) {
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
String fField = null;
|
||||
float fBoost = -1;
|
||||
float fBoost = AbstractQueryBuilder.DEFAULT_BOOST;
|
||||
char[] text = parser.textCharacters();
|
||||
int end = parser.textOffset() + parser.textLength();
|
||||
for (int i = parser.textOffset(); i < end; i++) {
|
||||
|
@ -100,148 +100,109 @@ public class QueryStringQueryParser extends BaseQueryParserTemp {
|
|||
if (fField == null) {
|
||||
fField = parser.text();
|
||||
}
|
||||
if (qpSettings.fields() == null) {
|
||||
qpSettings.fields(new ArrayList<String>());
|
||||
}
|
||||
|
||||
if (Regex.isSimpleMatchPattern(fField)) {
|
||||
for (String field : context.mapperService().simpleMatchToIndexNames(fField)) {
|
||||
qpSettings.fields().add(field);
|
||||
if (fBoost != -1) {
|
||||
if (qpSettings.boosts() == null) {
|
||||
qpSettings.boosts(new ObjectFloatHashMap<String>());
|
||||
}
|
||||
qpSettings.boosts().put(field, fBoost);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qpSettings.fields().add(fField);
|
||||
if (fBoost != -1) {
|
||||
if (qpSettings.boosts() == null) {
|
||||
qpSettings.boosts(new ObjectFloatHashMap<String>());
|
||||
}
|
||||
qpSettings.boosts().put(fField, fBoost);
|
||||
}
|
||||
}
|
||||
fieldsAndWeights.put(fField, fBoost);
|
||||
}
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext, "[query_string] query does not support [" + currentFieldName
|
||||
+ "]");
|
||||
throw new QueryParsingException(parseContext, "[query_string] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("query".equals(currentFieldName)) {
|
||||
qpSettings.queryString(parser.text());
|
||||
queryString = parser.text();
|
||||
} else if ("default_field".equals(currentFieldName) || "defaultField".equals(currentFieldName)) {
|
||||
qpSettings.defaultField(parser.text());
|
||||
defaultField = parser.text();
|
||||
} else if ("default_operator".equals(currentFieldName) || "defaultOperator".equals(currentFieldName)) {
|
||||
String op = parser.text();
|
||||
if ("or".equalsIgnoreCase(op)) {
|
||||
qpSettings.defaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.OR);
|
||||
} else if ("and".equalsIgnoreCase(op)) {
|
||||
qpSettings.defaultOperator(org.apache.lucene.queryparser.classic.QueryParser.Operator.AND);
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext, "Query default operator [" + op + "] is not allowed");
|
||||
}
|
||||
defaultOperator = Operator.fromString(parser.text());
|
||||
} else if ("analyzer".equals(currentFieldName)) {
|
||||
NamedAnalyzer analyzer = context.analysisService().analyzer(parser.text());
|
||||
if (analyzer == null) {
|
||||
throw new QueryParsingException(parseContext, "[query_string] analyzer [" + parser.text() + "] not found");
|
||||
}
|
||||
qpSettings.forcedAnalyzer(analyzer);
|
||||
analyzer = parser.text();
|
||||
} else if ("quote_analyzer".equals(currentFieldName) || "quoteAnalyzer".equals(currentFieldName)) {
|
||||
NamedAnalyzer analyzer = context.analysisService().analyzer(parser.text());
|
||||
if (analyzer == null) {
|
||||
throw new QueryParsingException(parseContext, "[query_string] quote_analyzer [" + parser.text()
|
||||
+ "] not found");
|
||||
}
|
||||
qpSettings.forcedQuoteAnalyzer(analyzer);
|
||||
quoteAnalyzer = parser.text();
|
||||
} else if ("allow_leading_wildcard".equals(currentFieldName) || "allowLeadingWildcard".equals(currentFieldName)) {
|
||||
qpSettings.allowLeadingWildcard(parser.booleanValue());
|
||||
allowLeadingWildcard = parser.booleanValue();
|
||||
} else if ("auto_generate_phrase_queries".equals(currentFieldName) || "autoGeneratePhraseQueries".equals(currentFieldName)) {
|
||||
qpSettings.autoGeneratePhraseQueries(parser.booleanValue());
|
||||
autoGeneratePhraseQueries = parser.booleanValue();
|
||||
} else if ("max_determinized_states".equals(currentFieldName) || "maxDeterminizedStates".equals(currentFieldName)) {
|
||||
qpSettings.maxDeterminizedStates(parser.intValue());
|
||||
maxDeterminizedStates = parser.intValue();
|
||||
} else if ("lowercase_expanded_terms".equals(currentFieldName) || "lowercaseExpandedTerms".equals(currentFieldName)) {
|
||||
qpSettings.lowercaseExpandedTerms(parser.booleanValue());
|
||||
lowercaseExpandedTerms = parser.booleanValue();
|
||||
} else if ("enable_position_increments".equals(currentFieldName) || "enablePositionIncrements".equals(currentFieldName)) {
|
||||
qpSettings.enablePositionIncrements(parser.booleanValue());
|
||||
enablePositionIncrements = parser.booleanValue();
|
||||
} else if ("escape".equals(currentFieldName)) {
|
||||
qpSettings.escape(parser.booleanValue());
|
||||
escape = parser.booleanValue();
|
||||
} else if ("use_dis_max".equals(currentFieldName) || "useDisMax".equals(currentFieldName)) {
|
||||
qpSettings.useDisMax(parser.booleanValue());
|
||||
useDisMax = parser.booleanValue();
|
||||
} else if ("fuzzy_prefix_length".equals(currentFieldName) || "fuzzyPrefixLength".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyPrefixLength(parser.intValue());
|
||||
fuzzyPrefixLength = parser.intValue();
|
||||
} else if ("fuzzy_max_expansions".equals(currentFieldName) || "fuzzyMaxExpansions".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyMaxExpansions(parser.intValue());
|
||||
fuzzyMaxExpansions = parser.intValue();
|
||||
} else if ("fuzzy_rewrite".equals(currentFieldName) || "fuzzyRewrite".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyRewriteMethod(QueryParsers.parseRewriteMethod(parseContext.parseFieldMatcher(), parser.textOrNull()));
|
||||
fuzzyRewrite = parser.textOrNull();
|
||||
} else if ("phrase_slop".equals(currentFieldName) || "phraseSlop".equals(currentFieldName)) {
|
||||
qpSettings.phraseSlop(parser.intValue());
|
||||
phraseSlop = parser.intValue();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FUZZINESS)) {
|
||||
qpSettings.setFuzziness(Fuzziness.parse(parser));
|
||||
fuzziness = Fuzziness.parse(parser);
|
||||
} else if ("boost".equals(currentFieldName)) {
|
||||
qpSettings.boost(parser.floatValue());
|
||||
boost = parser.floatValue();
|
||||
} else if ("tie_breaker".equals(currentFieldName) || "tieBreaker".equals(currentFieldName)) {
|
||||
qpSettings.tieBreaker(parser.floatValue());
|
||||
tieBreaker = parser.floatValue();
|
||||
} else if ("analyze_wildcard".equals(currentFieldName) || "analyzeWildcard".equals(currentFieldName)) {
|
||||
qpSettings.analyzeWildcard(parser.booleanValue());
|
||||
analyzeWildcard = parser.booleanValue();
|
||||
} else if ("rewrite".equals(currentFieldName)) {
|
||||
qpSettings.rewriteMethod(QueryParsers.parseRewriteMethod(parseContext.parseFieldMatcher(), parser.textOrNull()));
|
||||
rewrite = parser.textOrNull();
|
||||
} else if ("minimum_should_match".equals(currentFieldName) || "minimumShouldMatch".equals(currentFieldName)) {
|
||||
qpSettings.minimumShouldMatch(parser.textOrNull());
|
||||
minimumShouldMatch = parser.textOrNull();
|
||||
} else if ("quote_field_suffix".equals(currentFieldName) || "quoteFieldSuffix".equals(currentFieldName)) {
|
||||
qpSettings.quoteFieldSuffix(parser.textOrNull());
|
||||
quoteFieldSuffix = parser.textOrNull();
|
||||
} else if ("lenient".equalsIgnoreCase(currentFieldName)) {
|
||||
qpSettings.lenient(parser.booleanValue());
|
||||
lenient = parser.booleanValue();
|
||||
} else if ("locale".equals(currentFieldName)) {
|
||||
String localeStr = parser.text();
|
||||
qpSettings.locale(LocaleUtils.parse(localeStr));
|
||||
} else if ("time_zone".equals(currentFieldName)) {
|
||||
locale = Locale.forLanguageTag(localeStr);
|
||||
} else if ("time_zone".equals(currentFieldName) || "timeZone".equals(currentFieldName)) {
|
||||
try {
|
||||
qpSettings.timeZone(DateTimeZone.forID(parser.text()));
|
||||
timeZone = parser.text();
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new QueryParsingException(parseContext,
|
||||
"[query_string] time_zone [" + parser.text() + "] is unknown");
|
||||
throw new QueryParsingException(parseContext, "[query_string] time_zone [" + parser.text() + "] is unknown");
|
||||
}
|
||||
} else if ("_name".equals(currentFieldName)) {
|
||||
queryName = parser.text();
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext, "[query_string] query does not support [" + currentFieldName
|
||||
+ "]");
|
||||
throw new QueryParsingException(parseContext, "[query_string] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qpSettings.queryString() == null) {
|
||||
if (queryString == null) {
|
||||
throw new QueryParsingException(parseContext, "query_string must be provided with a [query]");
|
||||
}
|
||||
qpSettings.defaultAnalyzer(context.mapperService().searchAnalyzer());
|
||||
qpSettings.defaultQuoteAnalyzer(context.mapperService().searchQuoteAnalyzer());
|
||||
|
||||
if (qpSettings.escape()) {
|
||||
qpSettings.queryString(org.apache.lucene.queryparser.classic.QueryParser.escape(qpSettings.queryString()));
|
||||
}
|
||||
|
||||
MapperQueryParser queryParser = context.queryParser(qpSettings);
|
||||
|
||||
try {
|
||||
Query query = queryParser.parse(qpSettings.queryString());
|
||||
if (query == null) {
|
||||
return null;
|
||||
}
|
||||
if (qpSettings.boost() != QueryParserSettings.DEFAULT_BOOST) {
|
||||
query.setBoost(query.getBoost() * qpSettings.boost());
|
||||
}
|
||||
query = fixNegativeQueryIfNeeded(query);
|
||||
if (query instanceof BooleanQuery) {
|
||||
query = Queries.applyMinimumShouldMatch((BooleanQuery) query, qpSettings.minimumShouldMatch());
|
||||
}
|
||||
if (queryName != null) {
|
||||
context.addNamedQuery(queryName, query);
|
||||
}
|
||||
return query;
|
||||
} catch (org.apache.lucene.queryparser.classic.ParseException e) {
|
||||
throw new QueryParsingException(parseContext, "Failed to parse query [" + qpSettings.queryString() + "]", e);
|
||||
}
|
||||
QueryStringQueryBuilder queryStringQuery = new QueryStringQueryBuilder(queryString);
|
||||
queryStringQuery.fields(fieldsAndWeights);
|
||||
queryStringQuery.defaultField(defaultField);
|
||||
queryStringQuery.defaultOperator(defaultOperator);
|
||||
queryStringQuery.analyzer(analyzer);
|
||||
queryStringQuery.quoteAnalyzer(quoteAnalyzer);
|
||||
queryStringQuery.allowLeadingWildcard(allowLeadingWildcard);
|
||||
queryStringQuery.autoGeneratePhraseQueries(autoGeneratePhraseQueries);
|
||||
queryStringQuery.maxDeterminizedStates(maxDeterminizedStates);
|
||||
queryStringQuery.lowercaseExpandedTerms(lowercaseExpandedTerms);
|
||||
queryStringQuery.enablePositionIncrements(enablePositionIncrements);
|
||||
queryStringQuery.escape(escape);
|
||||
queryStringQuery.useDisMax(useDisMax);
|
||||
queryStringQuery.fuzzyPrefixLength(fuzzyPrefixLength);
|
||||
queryStringQuery.fuzzyMaxExpansions(fuzzyMaxExpansions);
|
||||
queryStringQuery.fuzzyRewrite(fuzzyRewrite);
|
||||
queryStringQuery.phraseSlop(phraseSlop);
|
||||
queryStringQuery.fuzziness(fuzziness);
|
||||
queryStringQuery.tieBreaker(tieBreaker);
|
||||
queryStringQuery.analyzeWildcard(analyzeWildcard);
|
||||
queryStringQuery.rewrite(rewrite);
|
||||
queryStringQuery.minimumShouldMatch(minimumShouldMatch);
|
||||
queryStringQuery.quoteFieldSuffix(quoteFieldSuffix);
|
||||
queryStringQuery.lenient(lenient);
|
||||
queryStringQuery.timeZone(timeZone);
|
||||
queryStringQuery.locale(locale);
|
||||
queryStringQuery.boost(boost);
|
||||
queryStringQuery.queryName(queryName);
|
||||
return queryStringQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -79,7 +79,9 @@ import org.junit.BeforeClass;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -91,6 +93,7 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
|
|||
|
||||
private static final GeohashGenerator geohashGenerator = new GeohashGenerator();
|
||||
protected static final String STRING_FIELD_NAME = "mapped_string";
|
||||
protected static final String STRING_FIELD_NAME_2 = "mapped_string_2";
|
||||
protected static final String INT_FIELD_NAME = "mapped_int";
|
||||
protected static final String DOUBLE_FIELD_NAME = "mapped_double";
|
||||
protected static final String BOOLEAN_FIELD_NAME = "mapped_boolean";
|
||||
|
@ -176,6 +179,7 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
|
|||
String type = randomAsciiOfLengthBetween(1, 10);
|
||||
mapperService.merge(type, new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef(type,
|
||||
STRING_FIELD_NAME, "type=string",
|
||||
STRING_FIELD_NAME_2, "type=string",
|
||||
INT_FIELD_NAME, "type=integer",
|
||||
DOUBLE_FIELD_NAME, "type=double",
|
||||
BOOLEAN_FIELD_NAME, "type=boolean",
|
||||
|
@ -546,25 +550,39 @@ public abstract class BaseQueryTestCase<QB extends AbstractQueryBuilder<QB>> ext
|
|||
}
|
||||
|
||||
protected static Fuzziness randomFuzziness(String fieldName) {
|
||||
Fuzziness fuzziness = Fuzziness.AUTO;
|
||||
switch (fieldName) {
|
||||
case INT_FIELD_NAME:
|
||||
fuzziness = Fuzziness.build(randomIntBetween(3, 100));
|
||||
break;
|
||||
case DOUBLE_FIELD_NAME:
|
||||
fuzziness = Fuzziness.build(1 + randomFloat() * 10);
|
||||
break;
|
||||
case DATE_FIELD_NAME:
|
||||
fuzziness = Fuzziness.build(randomTimeValue());
|
||||
break;
|
||||
if (randomBoolean()) {
|
||||
return Fuzziness.fromEdits(randomIntBetween(0, 2));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
fuzziness = Fuzziness.fromEdits(randomIntBetween(0, 2));
|
||||
return Fuzziness.AUTO;
|
||||
}
|
||||
switch (fieldName) {
|
||||
case INT_FIELD_NAME:
|
||||
return Fuzziness.build(randomIntBetween(3, 100));
|
||||
case DOUBLE_FIELD_NAME:
|
||||
return Fuzziness.build(1 + randomFloat() * 10);
|
||||
case DATE_FIELD_NAME:
|
||||
return Fuzziness.build(randomTimeValue());
|
||||
default:
|
||||
return Fuzziness.AUTO;
|
||||
}
|
||||
return fuzziness;
|
||||
}
|
||||
|
||||
protected static boolean isNumericFieldName(String fieldName) {
|
||||
return INT_FIELD_NAME.equals(fieldName) || DOUBLE_FIELD_NAME.equals(fieldName);
|
||||
}
|
||||
|
||||
protected static String randomAnalyzer() {
|
||||
return randomFrom("simple", "standard", "keyword", "whitespace");
|
||||
}
|
||||
|
||||
protected static String randomMinimumShouldMatch() {
|
||||
return randomFrom("1", "-1", "75%", "-25%", "2<75%", "2<-25%");
|
||||
}
|
||||
|
||||
protected static String randomTimeZone() {
|
||||
return randomFrom(TIMEZONE_IDS);
|
||||
}
|
||||
|
||||
private static final List<String> TIMEZONE_IDS = new ArrayList<>(DateTimeZone.getAvailableIDs());
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class BoolQueryBuilderTests extends BaseQueryTestCase<BoolQueryBuilder> {
|
|||
query.disableCoord(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
query.minimumNumberShouldMatch(randomIntBetween(1, 10));
|
||||
query.minimumNumberShouldMatch(randomMinimumShouldMatch());
|
||||
}
|
||||
int mustClauses = randomIntBetween(0, 3);
|
||||
for (int i = 0; i < mustClauses; i++) {
|
||||
|
|
|
@ -66,7 +66,7 @@ public class CommonTermsQueryBuilderTests extends BaseQueryTestCase<CommonTermsQ
|
|||
}
|
||||
|
||||
if (randomBoolean()) {
|
||||
query.analyzer(randomFrom("simple", "keyword", "whitespace"));
|
||||
query.analyzer(randomAnalyzer());
|
||||
}
|
||||
|
||||
if (randomBoolean()) {
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* 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.query;
|
||||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.apache.lucene.util.automaton.TooComplexToDeterminizeException;
|
||||
import org.elasticsearch.common.lucene.all.AllTermQuery;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
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.*;
|
||||
|
||||
public class QueryStringQueryBuilderTests extends BaseQueryTestCase<QueryStringQueryBuilder> {
|
||||
|
||||
@Override
|
||||
protected QueryStringQueryBuilder doCreateTestQueryBuilder() {
|
||||
int numTerms = randomIntBetween(0, 5);
|
||||
String query = "";
|
||||
for (int i = 0; i < numTerms; i++) {
|
||||
//min length 4 makes sure that the text is not an operator (AND/OR) so toQuery won't break
|
||||
query += (randomBoolean() ? STRING_FIELD_NAME + ":" : "") + randomAsciiOfLengthBetween(4, 10) + " ";
|
||||
}
|
||||
QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(query);
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.defaultField(randomBoolean() ? STRING_FIELD_NAME : randomAsciiOfLengthBetween(1, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
int numFields = randomIntBetween(1, 5);
|
||||
for (int i = 0; i < numFields; i++) {
|
||||
String fieldName = randomBoolean() ? STRING_FIELD_NAME : randomAsciiOfLengthBetween(1, 10);
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.field(fieldName);
|
||||
} else {
|
||||
queryStringQueryBuilder.field(fieldName, randomFloat());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.defaultOperator(randomFrom(Operator.values()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
//we only use string fields (either mapped or unmapped)
|
||||
queryStringQueryBuilder.fuzziness(randomFuzziness(STRING_FIELD_NAME));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.analyzer(randomAnalyzer());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.quoteAnalyzer(randomAnalyzer());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.allowLeadingWildcard(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.analyzeWildcard(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.maxDeterminizedStates(randomIntBetween(1, 100));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.lowercaseExpandedTerms(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.autoGeneratePhraseQueries(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.enablePositionIncrements(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.lenient(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.escape(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.phraseSlop(randomIntBetween(0, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.fuzzyMaxExpansions(randomIntBetween(0, 100));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.fuzzyPrefixLength(randomIntBetween(0, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.fuzzyRewrite(getRandomRewriteMethod());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.rewrite(getRandomRewriteMethod());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.quoteFieldSuffix(randomAsciiOfLengthBetween(1, 3));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.tieBreaker(randomFloat());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.minimumShouldMatch(randomMinimumShouldMatch());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.useDisMax(randomBoolean());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.locale(randomLocale(getRandom()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
queryStringQueryBuilder.timeZone(randomTimeZone());
|
||||
}
|
||||
return queryStringQueryBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAssertLuceneQuery(QueryStringQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
||||
if ("".equals(queryBuilder.queryString())) {
|
||||
assertThat(query, instanceOf(MatchNoDocsQuery.class));
|
||||
} else {
|
||||
assertThat(query, either(instanceOf(TermQuery.class)).or(instanceOf(AllTermQuery.class))
|
||||
.or(instanceOf(BooleanQuery.class)).or(instanceOf(DisjunctionMaxQuery.class)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidate() {
|
||||
QueryValidationException queryValidationException = createTestQueryBuilder().validate();
|
||||
assertNull(queryValidationException);
|
||||
|
||||
queryValidationException = new QueryStringQueryBuilder(null).validate();
|
||||
assertNotNull(queryValidationException);
|
||||
assertThat(queryValidationException.validationErrors().size(), equalTo(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryMatchAllQuery() throws Exception {
|
||||
Query query = queryStringQuery("*:*").toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(MatchAllDocsQuery.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryTermQuery() throws IOException {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test").defaultField(STRING_FIELD_NAME).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(TermQuery.class));
|
||||
TermQuery termQuery = (TermQuery) query;
|
||||
assertThat(termQuery.getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryPhraseQuery() throws IOException {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("\"term1 term2\"").defaultField(STRING_FIELD_NAME).phraseSlop(3).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(DisjunctionMaxQuery.class));
|
||||
DisjunctionMaxQuery disjunctionMaxQuery = (DisjunctionMaxQuery) query;
|
||||
assertThat(disjunctionMaxQuery.getDisjuncts().size(), equalTo(1));
|
||||
assertThat(disjunctionMaxQuery.getDisjuncts().get(0), instanceOf(PhraseQuery.class));
|
||||
PhraseQuery phraseQuery = (PhraseQuery)disjunctionMaxQuery.getDisjuncts().get(0);
|
||||
assertThat(phraseQuery.getTerms().length, equalTo(2));
|
||||
assertThat(phraseQuery.getTerms()[0], equalTo(new Term(STRING_FIELD_NAME, "term1")));
|
||||
assertThat(phraseQuery.getTerms()[1], equalTo(new Term(STRING_FIELD_NAME, "term2")));
|
||||
assertThat(phraseQuery.getSlop(), equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryBoosts() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
QueryShardContext shardContext = createShardContext();
|
||||
QueryStringQueryBuilder queryStringQuery = queryStringQuery(STRING_FIELD_NAME + ":boosted^2");
|
||||
Query query = queryStringQuery.toQuery(shardContext);
|
||||
assertThat(query, instanceOf(TermQuery.class));
|
||||
assertThat(((TermQuery) query).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "boosted")));
|
||||
assertThat(query.getBoost(), equalTo(2.0f));
|
||||
queryStringQuery.boost(2.0f);
|
||||
query = queryStringQuery.toQuery(shardContext);
|
||||
assertThat(query.getBoost(), equalTo(4.0f));
|
||||
|
||||
queryStringQuery = queryStringQuery("((" + STRING_FIELD_NAME + ":boosted^2) AND (" + STRING_FIELD_NAME + ":foo^1.5))^3");
|
||||
query = queryStringQuery.toQuery(shardContext);
|
||||
assertThat(query, instanceOf(BooleanQuery.class));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 0).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "boosted")));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 0).getBoost(), equalTo(2.0f));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "foo")));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getBoost(), equalTo(1.5f));
|
||||
assertThat(query.getBoost(), equalTo(3.0f));
|
||||
queryStringQuery.boost(2.0f);
|
||||
query = queryStringQuery.toQuery(shardContext);
|
||||
assertThat(query.getBoost(), equalTo(6.0f));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryMultipleTermsBooleanQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test1 test2").field(STRING_FIELD_NAME).useDisMax(false).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bQuery = (BooleanQuery) query;
|
||||
assertThat(bQuery.clauses().size(), equalTo(2));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 0).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test1")));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test2")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryMultipleFieldsBooleanQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test").field(STRING_FIELD_NAME).field(STRING_FIELD_NAME_2).useDisMax(false).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bQuery = (BooleanQuery) query;
|
||||
assertThat(bQuery.clauses().size(), equalTo(2));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 0).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test")));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryMultipleFieldsDisMaxQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test").field(STRING_FIELD_NAME).field(STRING_FIELD_NAME_2).useDisMax(true).toQuery(createShardContext());
|
||||
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(((TermQuery) disjuncts.get(1)).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryFieldsWildcard() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test").field("mapped_str*").useDisMax(false).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(BooleanQuery.class));
|
||||
BooleanQuery bQuery = (BooleanQuery) query;
|
||||
assertThat(bQuery.clauses().size(), equalTo(2));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 0).getTerm(), equalTo(new Term(STRING_FIELD_NAME, "test")));
|
||||
assertThat(assertBooleanSubQuery(query, TermQuery.class, 1).getTerm(), equalTo(new Term(STRING_FIELD_NAME_2, "test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryDisMaxQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("test").field(STRING_FIELD_NAME, 2.2f).field(STRING_FIELD_NAME_2).useDisMax(true).toQuery(createShardContext());
|
||||
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));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryRegExpQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("/foo*bar/").defaultField(STRING_FIELD_NAME).maxDeterminizedStates(5000).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(RegexpQuery.class));
|
||||
RegexpQuery regexpQuery = (RegexpQuery) query;
|
||||
assertTrue(regexpQuery.toString().contains("/foo*bar/"));
|
||||
}
|
||||
|
||||
@Test(expected = TooComplexToDeterminizeException.class)
|
||||
public void testToQueryRegExpQueryTooComplex() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
queryStringQuery("/[ac]*a[ac]{50,200}/").defaultField(STRING_FIELD_NAME).toQuery(createShardContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToQueryNumericRangeQuery() throws Exception {
|
||||
assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0);
|
||||
Query query = queryStringQuery("12~0.2").defaultField(INT_FIELD_NAME).toQuery(createShardContext());
|
||||
assertThat(query, instanceOf(NumericRangeQuery.class));
|
||||
|
||||
}
|
||||
}
|
|
@ -27,16 +27,12 @@ import org.joda.time.DateTimeZone;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class RangeQueryBuilderTests extends BaseQueryTestCase<RangeQueryBuilder> {
|
||||
|
||||
private static final List<String> TIMEZONE_IDS = new ArrayList<>(DateTimeZone.getAvailableIDs());
|
||||
|
||||
@Override
|
||||
protected RangeQueryBuilder doCreateTestQueryBuilder() {
|
||||
RangeQueryBuilder query;
|
||||
|
@ -64,7 +60,7 @@ public class RangeQueryBuilderTests extends BaseQueryTestCase<RangeQueryBuilder>
|
|||
// otherwise we could trigger exception.
|
||||
if (createShardContext().mapperService().smartNameFieldType(DATE_FIELD_NAME) != null) {
|
||||
if (randomBoolean()) {
|
||||
query.timeZone(TIMEZONE_IDS.get(randomIntBetween(0, TIMEZONE_IDS.size() - 1)));
|
||||
query.timeZone(randomTimeZone());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
query.format("yyyy-MM-dd'T'HH:mm:ss.SSSZZ");
|
||||
|
|
|
@ -34,8 +34,6 @@ import static org.hamcrest.Matchers.*;
|
|||
|
||||
public class SimpleQueryStringBuilderTests extends BaseQueryTestCase<SimpleQueryStringBuilder> {
|
||||
|
||||
private static final String[] MINIMUM_SHOULD_MATCH = new String[] { "1", "-1", "75%", "-25%", "2<75%", "2<-25%" };
|
||||
|
||||
@Override
|
||||
protected SimpleQueryStringBuilder doCreateTestQueryBuilder() {
|
||||
SimpleQueryStringBuilder result = new SimpleQueryStringBuilder(randomAsciiOfLengthBetween(1, 10));
|
||||
|
@ -52,13 +50,13 @@ public class SimpleQueryStringBuilderTests extends BaseQueryTestCase<SimpleQuery
|
|||
result.locale(randomLocale(getRandom()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
result.minimumShouldMatch(randomFrom(MINIMUM_SHOULD_MATCH));
|
||||
result.minimumShouldMatch(randomMinimumShouldMatch());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
result.analyzer("simple");
|
||||
result.analyzer(randomAnalyzer());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
result.defaultOperator(randomFrom(Operator.AND, Operator.OR));
|
||||
result.defaultOperator(randomFrom(Operator.values()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
Set<SimpleQueryStringFlag> flagSet = new HashSet<>();
|
||||
|
@ -72,12 +70,12 @@ public class SimpleQueryStringBuilderTests extends BaseQueryTestCase<SimpleQuery
|
|||
}
|
||||
|
||||
int fieldCount = randomIntBetween(0, 10);
|
||||
Map<String, Float> fields = new TreeMap<>();
|
||||
Map<String, Float> fields = new HashMap<>();
|
||||
for (int i = 0; i < fieldCount; i++) {
|
||||
if (randomBoolean()) {
|
||||
fields.put(randomAsciiOfLengthBetween(1, 10), AbstractQueryBuilder.DEFAULT_BOOST);
|
||||
} else {
|
||||
fields.put(randomAsciiOfLengthBetween(1, 10), 2.0f / randomIntBetween(1, 20));
|
||||
fields.put(randomBoolean() ? STRING_FIELD_NAME : randomAsciiOfLengthBetween(1, 10), 2.0f / randomIntBetween(1, 20));
|
||||
}
|
||||
}
|
||||
result.fields(fields);
|
||||
|
@ -274,22 +272,12 @@ public class SimpleQueryStringBuilderTests extends BaseQueryTestCase<SimpleQuery
|
|||
for (BooleanClause booleanClause : boolQuery) {
|
||||
assertThat(booleanClause.getQuery(), instanceOf(TermQuery.class));
|
||||
TermQuery termQuery = (TermQuery) booleanClause.getQuery();
|
||||
assertThat(termQuery.getTerm(), equalTo(new Term(fields.next(), queryBuilder.value().toLowerCase(Locale.ROOT))));
|
||||
assertThat(termQuery.getTerm().field(), equalTo(fields.next()));
|
||||
assertThat(termQuery.getTerm().text().toLowerCase(Locale.ROOT), equalTo(queryBuilder.value().toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
|
||||
if (queryBuilder.minimumShouldMatch() != null) {
|
||||
Collection<String> minMatchAlways = Arrays.asList("1", "-1", "75%", "-25%");
|
||||
Collection<String> minMatchLarger = Arrays.asList("2<75%", "2<-25%");
|
||||
|
||||
if (minMatchAlways.contains(queryBuilder.minimumShouldMatch())) {
|
||||
assertThat(boolQuery.getMinimumNumberShouldMatch(), greaterThan(0));
|
||||
} else if (minMatchLarger.contains(queryBuilder.minimumShouldMatch())) {
|
||||
if (shouldClauses(boolQuery) > 2) {
|
||||
assertThat(boolQuery.getMinimumNumberShouldMatch(), greaterThan(0));
|
||||
}
|
||||
} else {
|
||||
assertEquals(0, boolQuery.getMinimumNumberShouldMatch());
|
||||
}
|
||||
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);
|
||||
|
@ -301,11 +289,8 @@ public class SimpleQueryStringBuilderTests extends BaseQueryTestCase<SimpleQuery
|
|||
} else {
|
||||
field = queryBuilder.fields().keySet().iterator().next();
|
||||
}
|
||||
assertThat(termQuery.getTerm(), equalTo(new Term(field, queryBuilder.value().toLowerCase(Locale.ROOT))));
|
||||
|
||||
if (queryBuilder.lowercaseExpandedTerms()) {
|
||||
assertThat(termQuery.getTerm().bytes().toString(), is(termQuery.getTerm().bytes().toString().toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
assertThat(termQuery.getTerm().field(), equalTo(field));
|
||||
assertThat(termQuery.getTerm().text().toLowerCase(Locale.ROOT), equalTo(queryBuilder.value().toLowerCase(Locale.ROOT)));
|
||||
} else {
|
||||
fail("Encountered lucene query type we do not have a validation implementation for in our " + SimpleQueryStringBuilderTests.class.getSimpleName());
|
||||
}
|
||||
|
|
|
@ -964,12 +964,12 @@ public class HighlighterSearchIT extends ESIntegTestCase {
|
|||
assertHighlight(resp, 0, "foo", 0, equalTo("junk junk <em>cats</em> junk junk"));
|
||||
|
||||
// which can also be written by searching on the subfield
|
||||
resp = req.setQuery(queryStringQuery("cats").field("foo").field("foo.plain^5")).get();
|
||||
resp = req.setQuery(queryStringQuery("cats").field("foo").field("foo.plain", 5)).get();
|
||||
assertHighlight(resp, 0, "foo", 0, equalTo("junk junk <em>cats</em> junk junk"));
|
||||
|
||||
// Speaking of two fields, you can have two fields, only one of which has matchedFields enabled
|
||||
QueryBuilder twoFieldsQuery = queryStringQuery("cats").field("foo").field("foo.plain^5")
|
||||
.field("bar").field("bar.plain^5");
|
||||
QueryBuilder twoFieldsQuery = queryStringQuery("cats").field("foo").field("foo.plain", 5)
|
||||
.field("bar").field("bar.plain", 5);
|
||||
resp = req.setQuery(twoFieldsQuery).addHighlightedField(barField).get();
|
||||
assertHighlight(resp, 0, "foo", 0, equalTo("junk junk <em>cats</em> junk junk"));
|
||||
assertHighlight(resp, 0, "bar", 0, equalTo("<em>cat</em> <em>cat</em> junk junk junk junk"));
|
||||
|
@ -2610,7 +2610,7 @@ public class HighlighterSearchIT extends ESIntegTestCase {
|
|||
// Query string boosting the field
|
||||
phraseBoostTestCaseForClauses(highlighterType, 1f,
|
||||
queryStringQuery("highlight words together").field("field1"),
|
||||
queryStringQuery("\"highlight words together\"").field("field1^100").autoGeneratePhraseQueries(true));
|
||||
queryStringQuery("\"highlight words together\"").field("field1", 100).autoGeneratePhraseQueries(true));
|
||||
}
|
||||
|
||||
private <P extends AbstractQueryBuilder<P>> void
|
||||
|
|
|
@ -59,6 +59,11 @@ Removed `wrapperQueryBuilder(byte[] source, int offset, int length)`. Instead si
|
|||
use `wrapperQueryBuilder(byte[] source)`. Updated the static factory methods in
|
||||
QueryBuilders accordingly.
|
||||
|
||||
==== QueryStringQueryBuilder
|
||||
|
||||
Removed ability to pass in boost value using `field(String field)` method in form e.g. `field^2`.
|
||||
Use the `field(String, float)` method instead.
|
||||
|
||||
==== Operator
|
||||
|
||||
Removed the enums called `Operator` from `MatchQueryBuilder`, `QueryStringQueryBuilder`,
|
||||
|
|
Loading…
Reference in New Issue