diff --git a/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/MapperQueryParser.java b/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/MapperQueryParser.java index 758fda70c14..e9c68854be7 100644 --- a/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/MapperQueryParser.java +++ b/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/MapperQueryParser.java @@ -24,7 +24,6 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.index.Term; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.FuzzyQuery; -import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.Query; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.io.FastStringReader; @@ -84,7 +83,7 @@ public class MapperQueryParser extends QueryParser { public void reset(QueryParserSettings settings) { this.field = settings.defaultField(); this.analyzer = settings.analyzer(); - setMultiTermRewriteMethod(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT); + setMultiTermRewriteMethod(settings.rewriteMethod()); setEnablePositionIncrements(settings.enablePositionIncrements()); setAutoGeneratePhraseQueries(settings.autoGeneratePhraseQueries()); setAllowLeadingWildcard(settings.allowLeadingWildcard()); diff --git a/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/QueryParserSettings.java b/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/QueryParserSettings.java index 9790ea6d821..cc2a83e874d 100644 --- a/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/QueryParserSettings.java +++ b/modules/elasticsearch/src/main/java/org/apache/lucene/queryParser/QueryParserSettings.java @@ -21,6 +21,7 @@ package org.apache.lucene.queryParser; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.search.FuzzyQuery; +import org.apache.lucene.search.MultiTermQuery; /** * @author kimchy (shay.banon) @@ -41,6 +42,7 @@ public class QueryParserSettings { private boolean analyzeWildcard = false; private boolean escape = false; private Analyzer analyzer = null; + private MultiTermQuery.RewriteMethod rewriteMethod = MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT; public String queryString() { return queryString; @@ -154,6 +156,14 @@ public class QueryParserSettings { this.analyzeWildcard = analyzeWildcard; } + public MultiTermQuery.RewriteMethod rewriteMethod() { + return this.rewriteMethod; + } + + public void rewriteMethod(MultiTermQuery.RewriteMethod rewriteMethod) { + this.rewriteMethod = rewriteMethod; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryBuilder.java index 4cd08c20598..a4b798a26fc 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryBuilder.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryBuilder.java @@ -65,6 +65,8 @@ public class FieldQueryBuilder extends BaseQueryBuilder { private boolean extraSet = false; + private String rewrite; + /** * A query that executes the query string against a field. It is a simplified * version of {@link QueryStringQueryBuilder} that simply runs against @@ -268,6 +270,12 @@ public class FieldQueryBuilder extends BaseQueryBuilder { return this; } + public FieldQueryBuilder rewrite(String rewrite) { + this.rewrite = rewrite; + extraSet = true; + return this; + } + @Override public void doXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(FieldQueryParser.NAME); if (!extraSet) { @@ -308,6 +316,9 @@ public class FieldQueryBuilder extends BaseQueryBuilder { if (analyzeWildcard != null) { builder.field("analyze_wildcard", analyzeWildcard); } + if (rewrite != null) { + builder.field("rewrite", rewrite); + } builder.endObject(); } builder.endObject(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryParser.java index a4505372d47..4a9fc7d1dd0 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/FieldQueryParser.java @@ -25,6 +25,7 @@ import org.apache.lucene.queryParser.QueryParserSettings; import org.apache.lucene.search.Query; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; @@ -93,6 +94,8 @@ public class FieldQueryParser implements QueryParser { qpSettings.escape(parser.booleanValue()); } else if ("analyze_wildcard".equals(currentFieldName) || "analyzeWildcard".equals(currentFieldName)) { qpSettings.analyzeWildcard(parser.booleanValue()); + } else if ("rewrite".equals(currentFieldName)) { + qpSettings.rewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull())); } } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java index 2f28041c895..02d90def3ad 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryBuilder.java @@ -36,6 +36,8 @@ public class PrefixQueryBuilder extends BaseQueryBuilder { private float boost = -1; + private String rewrite; + /** * A Query that matches documents containing terms with a specified prefix. * @@ -56,14 +58,24 @@ public class PrefixQueryBuilder extends BaseQueryBuilder { return this; } + public PrefixQueryBuilder rewrite(String rewrite) { + this.rewrite = rewrite; + return this; + } + @Override public void doXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(PrefixQueryParser.NAME); - if (boost == -1) { + if (boost == -1 && rewrite == null) { builder.field(name, prefix); } else { builder.startObject(name); builder.field("prefix", prefix); - builder.field("boost", boost); + if (boost != -1) { + builder.field("boost", boost); + } + if (rewrite != null) { + builder.field("rewrite", rewrite); + } builder.endObject(); } builder.endObject(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryParser.java index ecd7956562f..19fd9435c9a 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/PrefixQueryParser.java @@ -20,12 +20,12 @@ package org.elasticsearch.index.query; import org.apache.lucene.index.Term; -import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.PrefixQuery; 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; @@ -51,7 +51,7 @@ public class PrefixQueryParser implements QueryParser { XContentParser.Token token = parser.nextToken(); assert token == XContentParser.Token.FIELD_NAME; String fieldName = parser.currentName(); - + String rewriteMethod = null; String value = null; float boost = 1.0f; @@ -68,6 +68,8 @@ public class PrefixQueryParser implements QueryParser { value = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); + } else if ("rewrite".equals(currentFieldName)) { + rewriteMethod = parser.textOrNull(); } } } @@ -90,7 +92,7 @@ public class PrefixQueryParser implements QueryParser { } PrefixQuery query = new PrefixQuery(new Term(fieldName, value)); - query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT); + query.setRewriteMethod(QueryParsers.parseRewriteMethod(rewriteMethod)); query.setBoost(boost); return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java index 2a9350e846b..3c37b50a4f9 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryBuilder.java @@ -78,6 +78,8 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder { private float tieBreaker = -1; + private String rewrite = null; + public QueryStringQueryBuilder(String queryString) { this.queryString = queryString; } @@ -234,6 +236,11 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder { return this; } + public QueryStringQueryBuilder rewrite(String rewrite) { + this.rewrite = rewrite; + return this; + } + /** * Sets the boost for this query. Documents matching this query will (in addition to the normal * weightings) have their score multiplied by the boost provided. @@ -302,6 +309,9 @@ public class QueryStringQueryBuilder extends BaseQueryBuilder { if (analyzeWildcard != null) { builder.field("analyze_wildcard", analyzeWildcard); } + if (rewrite != null) { + builder.field("rewrite", rewrite); + } builder.endObject(); } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryParser.java index 376f782088b..18a13b52a5f 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/QueryStringQueryParser.java @@ -31,6 +31,7 @@ import org.elasticsearch.common.trove.impl.Constants; import org.elasticsearch.common.trove.map.hash.TObjectFloatHashMap; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.internal.AllFieldMapper; +import org.elasticsearch.index.query.support.QueryParsers; import java.io.IOException; @@ -144,6 +145,8 @@ public class QueryStringQueryParser implements QueryParser { qpSettings.tieBreaker(parser.floatValue()); } else if ("analyze_wildcard".equals(currentFieldName) || "analyzeWildcard".equals(currentFieldName)) { qpSettings.analyzeWildcard(parser.booleanValue()); + } else if ("rewrite".equals(currentFieldName)) { + qpSettings.rewriteMethod(QueryParsers.parseRewriteMethod(parser.textOrNull())); } } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java index 720e6896d7b..79589f53c0f 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryBuilder.java @@ -41,6 +41,8 @@ public class WildcardQueryBuilder extends BaseQueryBuilder { private float boost = -1; + private String rewrite; + /** * Implements the wildcard search query. Supported wildcards are *, which * matches any character sequence (including the empty one), and ?, @@ -57,6 +59,11 @@ public class WildcardQueryBuilder extends BaseQueryBuilder { this.wildcard = wildcard; } + public WildcardQueryBuilder rewrite(String rewrite) { + this.rewrite = rewrite; + return this; + } + /** * Sets the boost for this query. Documents matching this query will (in addition to the normal * weightings) have their score multiplied by the boost provided. @@ -68,12 +75,17 @@ public class WildcardQueryBuilder extends BaseQueryBuilder { @Override public void doXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(WildcardQueryParser.NAME); - if (boost == -1) { + if (boost == -1 && rewrite != null) { builder.field(name, wildcard); } else { builder.startObject(name); builder.field("wildcard", wildcard); - builder.field("boost", boost); + if (boost != -1) { + builder.field("boost", boost); + } + if (rewrite != null) { + builder.field("rewrite", rewrite); + } builder.endObject(); } builder.endObject(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java index 4c7b40855c2..8258c2527d9 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/WildcardQueryParser.java @@ -20,12 +20,12 @@ package org.elasticsearch.index.query; import org.apache.lucene.index.Term; -import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.WildcardQuery; 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; @@ -51,7 +51,7 @@ public class WildcardQueryParser implements QueryParser { XContentParser.Token token = parser.nextToken(); assert token == XContentParser.Token.FIELD_NAME; String fieldName = parser.currentName(); - + String rewriteMethod = null; String value = null; float boost = 1.0f; @@ -68,6 +68,8 @@ public class WildcardQueryParser implements QueryParser { value = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); + } else if ("rewrite".equals(currentFieldName)) { + rewriteMethod = parser.textOrNull(); } } } @@ -90,7 +92,7 @@ public class WildcardQueryParser implements QueryParser { } WildcardQuery query = new WildcardQuery(new Term(fieldName, value)); - query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT); + query.setRewriteMethod(QueryParsers.parseRewriteMethod(rewriteMethod)); query.setBoost(boost); return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/support/QueryParsers.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/support/QueryParsers.java index 7e5e2628edf..bb61ec3b43f 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/support/QueryParsers.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/query/support/QueryParsers.java @@ -21,7 +21,9 @@ package org.elasticsearch.index.query.support; import org.apache.lucene.search.Filter; import org.apache.lucene.search.FilteredQuery; +import org.apache.lucene.search.MultiTermQuery; import org.apache.lucene.search.Query; +import org.elasticsearch.ElasticSearchIllegalArgumentException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.collect.ImmutableList; import org.elasticsearch.common.lucene.search.AndFilter; @@ -38,6 +40,41 @@ public final class QueryParsers { } + public static MultiTermQuery.RewriteMethod parseRewriteMethod(@Nullable String rewriteMethod) { + if (rewriteMethod == null) { + return MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT; + } + if ("constant_score_auto".equals(rewriteMethod) || "constant_score_auto".equals(rewriteMethod)) { + return MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT; + } + if ("scoring_boolean".equals(rewriteMethod) || "scoringBoolean".equals(rewriteMethod)) { + return MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE; + } + if ("constant_score_boolean".equals(rewriteMethod) || "constantScoreBoolean".equals(rewriteMethod)) { + return MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE; + } + if ("constant_score_filter".equals(rewriteMethod) || "constantScoreFilter".equals(rewriteMethod)) { + return MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE; + } + if (rewriteMethod.startsWith("top_terms_")) { + int size = Integer.parseInt(rewriteMethod.substring("top_terms_".length())); + return new MultiTermQuery.TopTermsScoringBooleanQueryRewrite(size); + } + if (rewriteMethod.startsWith("topTerms")) { + int size = Integer.parseInt(rewriteMethod.substring("topTerms".length())); + return new MultiTermQuery.TopTermsScoringBooleanQueryRewrite(size); + } + if (rewriteMethod.startsWith("top_terms_boost_")) { + int size = Integer.parseInt(rewriteMethod.substring("top_terms_boost_".length())); + return new MultiTermQuery.TopTermsBoostOnlyBooleanQueryRewrite(size); + } + if (rewriteMethod.startsWith("topTermsBoost")) { + int size = Integer.parseInt(rewriteMethod.substring("topTermsBoost".length())); + return new MultiTermQuery.TopTermsBoostOnlyBooleanQueryRewrite(size); + } + throw new ElasticSearchIllegalArgumentException("Failed to parse rewrite_method [" + rewriteMethod + "]"); + } + public static Query wrapSmartNameQuery(Query query, @Nullable MapperService.SmartNameFieldMappers smartFieldMappers, QueryParseContext parseContext) { if (smartFieldMappers == null) {