From 14c11a94fbc1a1cc1c134cf51df37410d7f6ab21 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Wed, 22 Aug 2012 14:15:08 +0200 Subject: [PATCH] MinimumNumberShouldMatch inconcistency, closes #2194 Streamline the use of minimum should match to all relevant queries to accept `minimum_should_match`, and allow all relevant queries to accept the advanced "string" based config --- .../index/query/BoolQueryBuilder.java | 18 ++++++++++++------ .../index/query/BoolQueryParser.java | 13 ++++++------- .../index/query/TermsQueryBuilder.java | 13 +++++++++---- .../index/query/TermsQueryParser.java | 11 ++++++----- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java index 4b2c0945e3f..c786593caf1 100644 --- a/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java @@ -27,8 +27,6 @@ import java.util.List; /** * A Query that matches documents matching boolean combinations of other queries. - * - * */ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQueryBuilder { @@ -42,7 +40,7 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery private Boolean disableCoord; - private int minimumNumberShouldMatch = -1; + private String minimumShouldMatch; /** * Adds a query that must appear in the matching documents. @@ -103,7 +101,15 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery * @param minimumNumberShouldMatch the number of optional clauses that must match */ public BoolQueryBuilder minimumNumberShouldMatch(int minimumNumberShouldMatch) { - this.minimumNumberShouldMatch = minimumNumberShouldMatch; + this.minimumShouldMatch = Integer.toString(minimumNumberShouldMatch); + return this; + } + + /** + * Sets the minimum should match using the special syntax (for example, supporting percentage). + */ + public BoolQueryBuilder minimumShouldMatch(String minimumShouldMatch) { + this.minimumShouldMatch = minimumShouldMatch; return this; } @@ -126,8 +132,8 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery if (disableCoord != null) { builder.field("disable_coord", disableCoord); } - if (minimumNumberShouldMatch != -1) { - builder.field("minimum_number_should_match", minimumNumberShouldMatch); + if (minimumShouldMatch != null) { + builder.field("minimum_should_match", minimumShouldMatch); } builder.endObject(); } diff --git a/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java b/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java index da69ec8d1da..e35468819e9 100644 --- a/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java @@ -23,6 +23,7 @@ import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentParser; @@ -56,7 +57,7 @@ public class BoolQueryParser implements QueryParser { boolean disableCoord = false; float boost = 1.0f; - int minimumNumberShouldMatch = -1; + String minimumShouldMatch = null; List clauses = newArrayList(); @@ -112,12 +113,12 @@ public class BoolQueryParser implements QueryParser { } else if (token.isValue()) { if ("disable_coord".equals(currentFieldName) || "disableCoord".equals(currentFieldName)) { disableCoord = parser.booleanValue(); - } else if ("minimum_number_should_match".equals(currentFieldName) || "minimumNumberShouldMatch".equals(currentFieldName)) { - minimumNumberShouldMatch = parser.intValue(); } else if ("minimum_should_match".equals(currentFieldName) || "minimumShouldMatch".equals(currentFieldName)) { - minimumNumberShouldMatch = parser.intValue(); + minimumShouldMatch = parser.textOrNull(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); + } else if ("minimum_number_should_match".equals(currentFieldName) || "minimumNumberShouldMatch".equals(currentFieldName)) { + minimumShouldMatch = parser.textOrNull(); } else { throw new QueryParsingException(parseContext.index(), "[bool] query does not support [" + currentFieldName + "]"); } @@ -133,9 +134,7 @@ public class BoolQueryParser implements QueryParser { query.add(clause); } query.setBoost(boost); - if (minimumNumberShouldMatch != -1) { - query.setMinimumNumberShouldMatch(minimumNumberShouldMatch); - } + Queries.applyMinimumShouldMatch(query, minimumShouldMatch); return optimizeQuery(fixNegativeQueryIfNeeded(query)); } } diff --git a/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java index 55ab4b49b5c..6cac39aee8a 100644 --- a/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java +++ b/src/main/java/org/elasticsearch/index/query/TermsQueryBuilder.java @@ -32,7 +32,7 @@ public class TermsQueryBuilder extends BaseQueryBuilder implements BoostableQuer private final Object[] values; - private int minimumMatch = -1; + private String minimumShouldMatch; private Boolean disableCoord; @@ -119,7 +119,12 @@ public class TermsQueryBuilder extends BaseQueryBuilder implements BoostableQuer * Sets the minimum number of matches across the provided terms. Defaults to 1. */ public TermsQueryBuilder minimumMatch(int minimumMatch) { - this.minimumMatch = minimumMatch; + this.minimumShouldMatch = Integer.toString(minimumMatch); + return this; + } + + public TermsQueryBuilder minimumShouldMatch(String minimumShouldMatch) { + this.minimumShouldMatch = minimumShouldMatch; return this; } @@ -149,8 +154,8 @@ public class TermsQueryBuilder extends BaseQueryBuilder implements BoostableQuer } builder.endArray(); - if (minimumMatch != -1) { - builder.field("minimum_match", minimumMatch); + if (minimumShouldMatch != null) { + builder.field("minimum_should_match", minimumShouldMatch); } if (disableCoord != null) { builder.field("disable_coord", disableCoord); diff --git a/src/main/java/org/elasticsearch/index/query/TermsQueryParser.java b/src/main/java/org/elasticsearch/index/query/TermsQueryParser.java index 2dd885593ae..ceb7fd995e9 100644 --- a/src/main/java/org/elasticsearch/index/query/TermsQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/TermsQueryParser.java @@ -25,6 +25,7 @@ import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MapperService; @@ -65,7 +66,7 @@ public class TermsQueryParser implements QueryParser { String fieldName = null; boolean disableCoord = false; float boost = 1.0f; - int minimumNumberShouldMatch = 1; + String minimumShouldMatch = null; List values = newArrayList(); String currentFieldName = null; @@ -86,7 +87,9 @@ public class TermsQueryParser implements QueryParser { if ("disable_coord".equals(currentFieldName) || "disableCoord".equals(currentFieldName)) { disableCoord = parser.booleanValue(); } else if ("minimum_match".equals(currentFieldName) || "minimumMatch".equals(currentFieldName)) { - minimumNumberShouldMatch = parser.intValue(); + minimumShouldMatch = parser.textOrNull(); + } else if ("minimum_should_match".equals(currentFieldName) || "minimumShouldMatch".equals(currentFieldName)) { + minimumShouldMatch = parser.textOrNull(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } @@ -115,9 +118,7 @@ public class TermsQueryParser implements QueryParser { } } query.setBoost(boost); - if (minimumNumberShouldMatch != -1) { - query.setMinimumNumberShouldMatch(minimumNumberShouldMatch); - } + Queries.applyMinimumShouldMatch(query, minimumShouldMatch); return wrapSmartNameQuery(optimizeQuery(fixNegativeQueryIfNeeded(query)), smartNameFieldMappers, parseContext); } finally { if (smartNameFieldMappers != null && smartNameFieldMappers.explicitTypeInNameWithDocMapper()) {