Skip to content

Commit

Permalink
Add support for minimum_should_match to simple_query_string
Browse files Browse the repository at this point in the history
This behaves similar to the way that `minimum_should_match` works for
the `match` query (in fact it is implemented in the exact same way)

Fixes elastic#6449
  • Loading branch information
dakrone committed Feb 25, 2015
1 parent b16fb69 commit 2e9ea4a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 0 deletions.
Expand Up @@ -49,6 +49,11 @@ Defaults to `ROOT`.

|`lenient` | If set to `true` will cause format based failures
(like providing text to a numeric field) to be ignored.

|`minimum_should_match` | The minimum number of clauses that must match for a
document to be returned. See the
<<query-dsl-minimum-should-match,`minimum_should_match`>> documentation for the
full list of options.
|=======================================================================

[float]
Expand Down
Expand Up @@ -36,6 +36,7 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
private Operator operator;
private final String queryText;
private String queryName;
private String minimumShouldMatch;
private int flags = -1;
private Boolean lowercaseExpandedTerms;
private Boolean lenient;
Expand Down Expand Up @@ -134,6 +135,11 @@ public SimpleQueryStringBuilder analyzeWildcard(boolean analyzeWildcard) {
return this;
}

public SimpleQueryStringBuilder minimumShouldMatch(String minimumShouldMatch) {
this.minimumShouldMatch = minimumShouldMatch;
return this;
}

@Override
public void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(SimpleQueryStringParser.NAME);
Expand Down Expand Up @@ -186,6 +192,10 @@ public void doXContent(XContentBuilder builder, Params params) throws IOExceptio
builder.field("_name", queryName);
}

if (minimumShouldMatch != null) {
builder.field("minimum_should_match", minimumShouldMatch);
}

builder.endObject();
}
}
Expand Up @@ -21,9 +21,11 @@

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
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.util.LocaleUtils;
Expand Down Expand Up @@ -89,6 +91,7 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
String queryBody = null;
String queryName = null;
String field = null;
String minimumShouldMatch = null;
Map<String, Float> fieldsAndWeights = null;
BooleanClause.Occur defaultOperator = null;
Analyzer analyzer = null;
Expand Down Expand Up @@ -182,6 +185,8 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
sqsSettings.analyzeWildcard(parser.booleanValue());
} else if ("_name".equals(currentFieldName)) {
queryName = parser.text();
} else if ("minimum_should_match".equals(currentFieldName)) {
minimumShouldMatch = parser.textOrNull();
} else {
throw new QueryParsingException(parseContext.index(), "[" + NAME + "] unsupported field [" + parser.currentName() + "]");
}
Expand Down Expand Up @@ -221,6 +226,10 @@ public Query parse(QueryParseContext parseContext) throws IOException, QueryPars
if (queryName != null) {
parseContext.addNamedQuery(queryName, query);
}

if (minimumShouldMatch != null && query instanceof BooleanQuery) {
Queries.applyMinimumShouldMatch((BooleanQuery) query, minimumShouldMatch);
}
return query;
}
}
Expand Up @@ -91,6 +91,54 @@ public void testSimpleQueryString() throws ExecutionException, InterruptedExcept
assertSearchHits(searchResponse, "5", "6");
}

@Test
public void testSimpleQueryStringMinimumShouldMatch() throws Exception {
createIndex("test");
ensureGreen("test");
indexRandom(true, false,
client().prepareIndex("test", "type1", "1").setSource("body", "foo"),
client().prepareIndex("test", "type1", "2").setSource("body", "bar"),
client().prepareIndex("test", "type1", "3").setSource("body", "foo bar"),
client().prepareIndex("test", "type1", "4").setSource("body", "foo baz bar"));


logger.info("--> query 1");
SearchResponse searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar").minimumShouldMatch("2")).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "3", "4");

logger.info("--> query 2");
searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar").field("body").field("body2").minimumShouldMatch("2")).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "3", "4");

logger.info("--> query 3");
searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar baz").field("body").field("body2").minimumShouldMatch("70%")).get();
assertHitCount(searchResponse, 2l);
assertSearchHits(searchResponse, "3", "4");

indexRandom(true, false,
client().prepareIndex("test", "type1", "5").setSource("body2", "foo", "other", "foo"),
client().prepareIndex("test", "type1", "6").setSource("body2", "bar", "other", "foo"),
client().prepareIndex("test", "type1", "7").setSource("body2", "foo bar", "other", "foo"),
client().prepareIndex("test", "type1", "8").setSource("body2", "foo baz bar", "other", "foo"));

logger.info("--> query 4");
searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar").field("body").field("body2").minimumShouldMatch("2")).get();
assertHitCount(searchResponse, 4l);
assertSearchHits(searchResponse, "3", "4", "7", "8");

logger.info("--> query 5");
searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar").minimumShouldMatch("2")).get();
assertHitCount(searchResponse, 5l);
assertSearchHits(searchResponse, "3", "4", "6", "7", "8");

logger.info("--> query 6");
searchResponse = client().prepareSearch().setQuery(simpleQueryStringQuery("foo bar baz").field("body2").field("other").minimumShouldMatch("70%")).get();
assertHitCount(searchResponse, 3l);
assertSearchHits(searchResponse, "6", "7", "8");
}

@Test
public void testSimpleQueryStringLowercasing() {
createIndex("test");
Expand Down

0 comments on commit 2e9ea4a

Please sign in to comment.