Query DSL: Add more fuzzy options in different queries (text, query_string/field), closes #1974.
This commit is contained in:
parent
5cb3ea6ebc
commit
3bf55a0858
|
@ -33,6 +33,7 @@ import org.elasticsearch.index.mapper.FieldMapper;
|
|||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
@ -394,7 +395,7 @@ public class MapperQueryParser extends QueryParser {
|
|||
currentMapper = fieldMappers.fieldMappers().mapper();
|
||||
if (currentMapper != null) {
|
||||
try {
|
||||
Query fuzzyQuery = currentMapper.fuzzyQuery(termStr, minSimilarity, fuzzyPrefixLength, FuzzyQuery.defaultMaxExpansions);
|
||||
Query fuzzyQuery = currentMapper.fuzzyQuery(termStr, minSimilarity, fuzzyPrefixLength, settings.fuzzyMaxExpansions());
|
||||
return wrapSmartNameQuery(fuzzyQuery, fieldMappers, parseContext);
|
||||
} catch (RuntimeException e) {
|
||||
if (settings.lenient()) {
|
||||
|
@ -407,6 +408,13 @@ public class MapperQueryParser extends QueryParser {
|
|||
return super.getFuzzyQuery(field, termStr, minSimilarity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query newFuzzyQuery(Term term, float minimumSimilarity, int prefixLength) {
|
||||
FuzzyQuery query = new FuzzyQuery(term, minimumSimilarity, prefixLength, settings.fuzzyMaxExpansions());
|
||||
QueryParsers.setRewriteMethod(query, settings.fuzzyRewriteMethod());
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query getPrefixQuery(String field, String termStr) throws ParseException {
|
||||
Collection<String> fields = extractMultiFields(field);
|
||||
|
|
|
@ -45,6 +45,8 @@ public class QueryParserSettings {
|
|||
private int phraseSlop = 0;
|
||||
private float fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
|
||||
private int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
|
||||
private int fuzzyMaxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
private MultiTermQuery.RewriteMethod fuzzyRewriteMethod = null;
|
||||
private boolean analyzeWildcard = DEFAULT_ANALYZE_WILDCARD;
|
||||
private boolean escape = false;
|
||||
private Analyzer defaultAnalyzer = null;
|
||||
|
@ -150,6 +152,22 @@ public class QueryParserSettings {
|
|||
this.fuzzyPrefixLength = fuzzyPrefixLength;
|
||||
}
|
||||
|
||||
public int fuzzyMaxExpansions() {
|
||||
return fuzzyMaxExpansions;
|
||||
}
|
||||
|
||||
public void fuzzyMaxExpansions(int fuzzyMaxExpansions) {
|
||||
this.fuzzyMaxExpansions = fuzzyMaxExpansions;
|
||||
}
|
||||
|
||||
public MultiTermQuery.RewriteMethod fuzzyRewriteMethod() {
|
||||
return fuzzyRewriteMethod;
|
||||
}
|
||||
|
||||
public void fuzzyRewriteMethod(MultiTermQuery.RewriteMethod fuzzyRewriteMethod) {
|
||||
this.fuzzyRewriteMethod = fuzzyRewriteMethod;
|
||||
}
|
||||
|
||||
public boolean escape() {
|
||||
return escape;
|
||||
}
|
||||
|
@ -277,6 +295,9 @@ public class QueryParserSettings {
|
|||
if (analyzeWildcard != that.analyzeWildcard) return false;
|
||||
if (Float.compare(that.fuzzyMinSim, fuzzyMinSim) != 0) 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)
|
||||
|
|
|
@ -27,8 +27,6 @@ import java.io.IOException;
|
|||
* A query that executes the query string against a field. It is a simplified
|
||||
* version of {@link QueryStringQueryBuilder} that simply runs against
|
||||
* a single field.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class FieldQueryBuilder extends BaseQueryBuilder {
|
||||
|
||||
|
@ -55,12 +53,13 @@ public class FieldQueryBuilder extends BaseQueryBuilder {
|
|||
|
||||
private Boolean analyzeWildcard;
|
||||
|
||||
private int fuzzyPrefixLength = -1;
|
||||
private float fuzzyMinSim = -1;
|
||||
private int fuzzyMaxExpansions = -1;
|
||||
private String fuzzyRewrite;
|
||||
|
||||
private float boost = -1;
|
||||
|
||||
private int fuzzyPrefixLength = -1;
|
||||
|
||||
private int phraseSlop = -1;
|
||||
|
||||
private boolean extraSet = false;
|
||||
|
@ -253,6 +252,17 @@ public class FieldQueryBuilder extends BaseQueryBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public FieldQueryBuilder fuzzyMaxExpansions(int fuzzyMaxExpansions) {
|
||||
this.fuzzyMaxExpansions = fuzzyMaxExpansions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldQueryBuilder fuzzyRewrite(String fuzzyRewrite) {
|
||||
this.fuzzyRewrite = fuzzyRewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the default slop for phrases. If zero, then exact phrase matches
|
||||
* are required. Default value is zero.
|
||||
|
@ -318,6 +328,12 @@ public class FieldQueryBuilder extends BaseQueryBuilder {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -118,6 +118,10 @@ public class FieldQueryParser implements QueryParser {
|
|||
qpSettings.fuzzyMinSim(parser.floatValue());
|
||||
} else if ("fuzzy_prefix_length".equals(currentFieldName) || "fuzzyPrefixLength".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyPrefixLength(parser.intValue());
|
||||
} else if ("fuzzy_max_expansions".equals(currentFieldName) || "fuzzyMaxExpansions".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyMaxExpansions(parser.intValue());
|
||||
} else if ("fuzzy_rewrite".equals(currentFieldName) || "fuzzyRewrite".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyRewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull()));
|
||||
} else if ("escape".equals(currentFieldName)) {
|
||||
qpSettings.escape(parser.booleanValue());
|
||||
} else if ("analyze_wildcard".equals(currentFieldName) || "analyzeWildcard".equals(currentFieldName)) {
|
||||
|
|
|
@ -21,10 +21,12 @@ package org.elasticsearch.index.query;
|
|||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.MultiTermQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -61,6 +63,7 @@ public class FuzzyQueryParser implements QueryParser {
|
|||
String minSimilarity = "0.5";
|
||||
int prefixLength = FuzzyQuery.defaultPrefixLength;
|
||||
int maxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
MultiTermQuery.RewriteMethod rewriteMethod = null;
|
||||
token = parser.nextToken();
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
String currentFieldName = null;
|
||||
|
@ -80,6 +83,8 @@ public class FuzzyQueryParser implements QueryParser {
|
|||
prefixLength = parser.intValue();
|
||||
} else if ("max_expansions".equals(currentFieldName) || "maxExpansions".equals(currentFieldName)) {
|
||||
maxExpansions = parser.intValue();
|
||||
} else if ("rewrite".equals(currentFieldName)) {
|
||||
rewriteMethod = QueryParsers.parseRewriteMethod(parser.textOrNull(), null);
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[fuzzy] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
@ -106,6 +111,9 @@ public class FuzzyQueryParser implements QueryParser {
|
|||
if (query == null) {
|
||||
query = new FuzzyQuery(new Term(fieldName, value), Float.parseFloat(minSimilarity), prefixLength, maxExpansions);
|
||||
}
|
||||
if (query instanceof MultiTermQuery) {
|
||||
QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod);
|
||||
}
|
||||
query.setBoost(boost);
|
||||
|
||||
return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext);
|
||||
|
|
|
@ -91,7 +91,7 @@ public class PrefixQueryParser implements QueryParser {
|
|||
throw new QueryParsingException(parseContext.index(), "No value specified for prefix query");
|
||||
}
|
||||
|
||||
MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(rewriteMethod);
|
||||
MultiTermQuery.RewriteMethod method = QueryParsers.parseRewriteMethod(rewriteMethod, null);
|
||||
|
||||
Query query = null;
|
||||
MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
|
||||
|
|
|
@ -65,11 +65,13 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder {
|
|||
|
||||
private Boolean analyzeWildcard;
|
||||
|
||||
private float fuzzyMinSim = -1;
|
||||
|
||||
private float boost = -1;
|
||||
|
||||
private float fuzzyMinSim = -1;
|
||||
private int fuzzyPrefixLength = -1;
|
||||
private int fuzzyMaxExpansions = -1;
|
||||
private String fuzzyRewrite;
|
||||
|
||||
private int phraseSlop = -1;
|
||||
|
||||
|
@ -237,6 +239,16 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder fuzzyMaxExpansions(int fuzzyMaxExpansions) {
|
||||
this.fuzzyMaxExpansions = fuzzyMaxExpansions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryStringQueryBuilder fuzzyRewrite(String fuzzyRewrite) {
|
||||
this.fuzzyRewrite = fuzzyRewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default slop for phrases. If zero, then exact phrase matches
|
||||
* are required. Default value is zero.
|
||||
|
@ -347,6 +359,12 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -162,6 +162,10 @@ public class QueryStringQueryParser implements QueryParser {
|
|||
qpSettings.useDisMax(parser.booleanValue());
|
||||
} else if ("fuzzy_prefix_length".equals(currentFieldName) || "fuzzyPrefixLength".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyPrefixLength(parser.intValue());
|
||||
} else if ("fuzzy_max_expansions".equals(currentFieldName) || "fuzzyMaxExpansions".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyMaxExpansions(parser.intValue());
|
||||
} else if ("fuzzy_rewrite".equals(currentFieldName) || "fuzzyRewrite".equals(currentFieldName)) {
|
||||
qpSettings.fuzzyRewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull()));
|
||||
} else if ("phrase_slop".equals(currentFieldName) || "phraseSlop".equals(currentFieldName)) {
|
||||
qpSettings.phraseSlop(parser.intValue());
|
||||
} else if ("fuzzy_min_sim".equals(currentFieldName) || "fuzzyMinSim".equals(currentFieldName)) {
|
||||
|
|
|
@ -71,6 +71,9 @@ public class TextQueryBuilder extends BaseQueryBuilder {
|
|||
|
||||
private String minimumShouldMatch;
|
||||
|
||||
private String rewrite = null;
|
||||
private String fuzzyRewrite = null;
|
||||
|
||||
/**
|
||||
* Constructs a new text query.
|
||||
*/
|
||||
|
@ -147,6 +150,16 @@ public class TextQueryBuilder extends BaseQueryBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public TextQueryBuilder rewrite(String rewrite) {
|
||||
this.rewrite = rewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextQueryBuilder fuzzyRewrite(String fuzzyRewrite) {
|
||||
this.fuzzyRewrite = fuzzyRewrite;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(TextQueryParser.NAME);
|
||||
|
@ -180,6 +193,12 @@ public class TextQueryBuilder extends BaseQueryBuilder {
|
|||
if (minimumShouldMatch != null) {
|
||||
builder.field("minimum_should_match", minimumShouldMatch);
|
||||
}
|
||||
if (rewrite != null) {
|
||||
builder.field("rewrite", rewrite);
|
||||
}
|
||||
if (fuzzyRewrite != null) {
|
||||
builder.field("fuzzy_rewrite", fuzzyRewrite);
|
||||
}
|
||||
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
|
|
@ -19,13 +19,11 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.BooleanQuery;
|
||||
import org.apache.lucene.search.FuzzyQuery;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -71,6 +69,8 @@ public class TextQueryParser implements QueryParser {
|
|||
int maxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
BooleanClause.Occur occur = BooleanClause.Occur.SHOULD;
|
||||
String minimumShouldMatch = null;
|
||||
MultiTermQuery.RewriteMethod rewriteMethod = null;
|
||||
MultiTermQuery.RewriteMethod fuzzyRewriteMethod = null;
|
||||
|
||||
token = parser.nextToken();
|
||||
if (token == XContentParser.Token.START_OBJECT) {
|
||||
|
@ -116,6 +116,10 @@ public class TextQueryParser implements QueryParser {
|
|||
}
|
||||
} else if ("minimum_should_match".equals(currentFieldName) || "minimumShouldMatch".equals(currentFieldName)) {
|
||||
minimumShouldMatch = parser.textOrNull();
|
||||
} else if ("rewrite".equals(currentFieldName)) {
|
||||
rewriteMethod = QueryParsers.parseRewriteMethod(parser.textOrNull(), null);
|
||||
} else if ("fuzzy_rewrite".equals(currentFieldName) || "fuzzyRewrite".equals(currentFieldName)) {
|
||||
fuzzyRewriteMethod = QueryParsers.parseRewriteMethod(parser.textOrNull(), null);
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext.index(), "[text] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
|
@ -138,6 +142,8 @@ public class TextQueryParser implements QueryParser {
|
|||
tQP.setFuzziness(fuzziness);
|
||||
tQP.setFuzzyPrefixLength(prefixLength);
|
||||
tQP.setMaxExpansions(maxExpansions);
|
||||
tQP.setRewriteMethod(rewriteMethod);
|
||||
tQP.setFuzzyRewriteMethod(fuzzyRewriteMethod);
|
||||
tQP.setOccur(occur);
|
||||
|
||||
Query query = tQP.parse(type);
|
||||
|
|
|
@ -97,6 +97,7 @@ public class WildcardQueryParser implements QueryParser {
|
|||
}
|
||||
|
||||
WildcardQuery query = new WildcardQuery(new Term(fieldName, value));
|
||||
QueryParsers.setRewriteMethod(query, rewriteMethod);
|
||||
query.setRewriteMethod(QueryParsers.parseRewriteMethod(rewriteMethod));
|
||||
query.setBoost(boost);
|
||||
return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext);
|
||||
|
|
|
@ -40,9 +40,27 @@ public final class QueryParsers {
|
|||
|
||||
}
|
||||
|
||||
public static MultiTermQuery.RewriteMethod parseRewriteMethod(@Nullable String rewriteMethod) {
|
||||
public static void setRewriteMethod(MultiTermQuery query, @Nullable MultiTermQuery.RewriteMethod rewriteMethod) {
|
||||
if (rewriteMethod == null) {
|
||||
return MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
|
||||
return;
|
||||
}
|
||||
query.setRewriteMethod(rewriteMethod);
|
||||
}
|
||||
|
||||
public static void setRewriteMethod(MultiTermQuery query, @Nullable String rewriteMethod) {
|
||||
if (rewriteMethod == null) {
|
||||
return;
|
||||
}
|
||||
query.setRewriteMethod(parseRewriteMethod(rewriteMethod));
|
||||
}
|
||||
|
||||
public static MultiTermQuery.RewriteMethod parseRewriteMethod(@Nullable String rewriteMethod) {
|
||||
return parseRewriteMethod(rewriteMethod, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT);
|
||||
}
|
||||
|
||||
public static MultiTermQuery.RewriteMethod parseRewriteMethod(@Nullable String rewriteMethod, @Nullable MultiTermQuery.RewriteMethod defaultRewriteMethod) {
|
||||
if (rewriteMethod == null) {
|
||||
return defaultRewriteMethod;
|
||||
}
|
||||
if ("constant_score_auto".equals(rewriteMethod) || "constant_score_auto".equals(rewriteMethod)) {
|
||||
return MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
|
|||
import org.elasticsearch.index.mapper.FieldMapper;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.index.query.support.QueryParsers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -68,6 +69,9 @@ public class TextQueryParser {
|
|||
private int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
|
||||
private int maxExpansions = FuzzyQuery.defaultMaxExpansions;
|
||||
|
||||
private MultiTermQuery.RewriteMethod rewriteMethod;
|
||||
private MultiTermQuery.RewriteMethod fuzzyRewriteMethod;
|
||||
|
||||
public TextQueryParser(QueryParseContext parseContext, String fieldName, String text) {
|
||||
this.parseContext = parseContext;
|
||||
this.fieldName = fieldName;
|
||||
|
@ -102,6 +106,14 @@ public class TextQueryParser {
|
|||
this.maxExpansions = maxExpansions;
|
||||
}
|
||||
|
||||
public void setRewriteMethod(MultiTermQuery.RewriteMethod rewriteMethod) {
|
||||
this.rewriteMethod = rewriteMethod;
|
||||
}
|
||||
|
||||
public void setFuzzyRewriteMethod(MultiTermQuery.RewriteMethod fuzzyRewriteMethod) {
|
||||
this.fuzzyRewriteMethod = fuzzyRewriteMethod;
|
||||
}
|
||||
|
||||
public Query parse(Type type) {
|
||||
FieldMapper mapper = null;
|
||||
Term fieldTerm;
|
||||
|
@ -347,9 +359,14 @@ public class TextQueryParser {
|
|||
private Query newTermQuery(@Nullable FieldMapper mapper, Term term) {
|
||||
if (fuzziness != null) {
|
||||
if (mapper != null) {
|
||||
return mapper.fuzzyQuery(term.text(), fuzziness, fuzzyPrefixLength, maxExpansions);
|
||||
Query query = mapper.fuzzyQuery(term.text(), fuzziness, fuzzyPrefixLength, maxExpansions);
|
||||
if (query instanceof FuzzyQuery) {
|
||||
QueryParsers.setRewriteMethod((FuzzyQuery) query, fuzzyRewriteMethod);
|
||||
}
|
||||
return new FuzzyQuery(term, Float.parseFloat(fuzziness), fuzzyPrefixLength, maxExpansions);
|
||||
}
|
||||
FuzzyQuery query = new FuzzyQuery(term, Float.parseFloat(fuzziness), fuzzyPrefixLength, maxExpansions);
|
||||
QueryParsers.setRewriteMethod(query, rewriteMethod);
|
||||
return query;
|
||||
}
|
||||
if (mapper != null) {
|
||||
Query termQuery = mapper.queryStringTermQuery(term);
|
||||
|
|
Loading…
Reference in New Issue