Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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();
}
}
Original file line number Diff line number Diff line change
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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the best place to apply minShouldMatch. The difference between this and say match query is that it supports multiple fields (i realize the default is _all and this patch will work with that).

So in this case, this query will return a boolean query across say title, body, author fields. the current application of minShouldMatch will be unintuitive there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okay, I will do this in SimpleQueryParser instead

Queries.applyMinimumShouldMatch((BooleanQuery) query, minimumShouldMatch);
}
return query;
}
}
Original file line number Diff line number Diff line change
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