Queries.calculateMinShouldMatch returns the number of "min should match" clauses that the user wanted

even if the number of optional clauses is smaller than the provided number.
In such case the query now returns no result.
Closes #15521
This commit is contained in:
Jim Ferenczi 2015-12-21 14:29:48 +01:00
parent 1ec44dcdda
commit 4d32cc0b9f
4 changed files with 73 additions and 5 deletions

View File

@ -179,8 +179,6 @@ public class Queries {
result = calc < 0 ? result + calc : calc;
}
return (optionalClauseCount < result ?
optionalClauseCount : (result < 0 ? 0 : result));
return result < 0 ? 0 : result;
}
}

View File

@ -273,8 +273,7 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
return new MatchAllDocsQuery();
}
final String minimumShouldMatch;
if (context.isFilter() && this.minimumShouldMatch == null) {
//will be applied for real only if there are should clauses
if (context.isFilter() && this.minimumShouldMatch == null && shouldClauses.size() > 0) {
minimumShouldMatch = "1";
} else {
minimumShouldMatch = this.minimumShouldMatch;

View File

@ -254,6 +254,24 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
assertThat(innerBooleanClause2.getQuery(), instanceOf(MatchAllDocsQuery.class));
}
public void testMinShouldMatchBiggerThanNumberOfShouldClauses() throws Exception {
BooleanQuery bq = (BooleanQuery) parseQuery(
boolQuery()
.should(termQuery("foo", "bar"))
.should(termQuery("foo2", "bar2"))
.minimumNumberShouldMatch("3")
.buildAsBytes()).toQuery(createShardContext());
assertEquals(3, bq.getMinimumNumberShouldMatch());
bq = (BooleanQuery) parseQuery(
boolQuery()
.should(termQuery("foo", "bar"))
.should(termQuery("foo2", "bar2"))
.minimumNumberShouldMatch(3)
.buildAsBytes()).toQuery(createShardContext());
assertEquals(3, bq.getMinimumNumberShouldMatch());
}
public void testFromJson() throws IOException {
String query =
"{" +

View File

@ -1016,6 +1016,59 @@ public class SearchQueryIT extends ESIntegTestCase {
searchResponse = client().prepareSearch().setQuery(multiMatchQuery).get();
assertHitCount(searchResponse, 1l);
assertFirstHit(searchResponse, hasId("1"));
// Min should match > # optional clauses returns no docs.
multiMatchQuery = multiMatchQuery("value1 value2 value3", "field1", "field2");
multiMatchQuery.minimumShouldMatch("4");
searchResponse = client().prepareSearch().setQuery(multiMatchQuery).get();
assertHitCount(searchResponse, 0l);
}
public void testBoolQueryMinShouldMatchBiggerThanNumberOfShouldClauses() throws IOException {
createIndex("test");
client().prepareIndex("test", "type1", "1").setSource("field1", new String[]{"value1", "value2", "value3"}).get();
client().prepareIndex("test", "type1", "2").setSource("field2", "value1").get();
refresh();
BoolQueryBuilder boolQuery = boolQuery()
.must(termQuery("field1", "value1"))
.should(boolQuery()
.should(termQuery("field1", "value1"))
.should(termQuery("field1", "value2"))
.minimumNumberShouldMatch(3));
SearchResponse searchResponse = client().prepareSearch().setQuery(boolQuery).get();
assertHitCount(searchResponse, 1l);
assertFirstHit(searchResponse, hasId("1"));
boolQuery = boolQuery()
.must(termQuery("field1", "value1"))
.should(boolQuery()
.should(termQuery("field1", "value1"))
.should(termQuery("field1", "value2"))
.minimumNumberShouldMatch(1))
// Only one should clause is defined, returns no docs.
.minimumNumberShouldMatch(2);
searchResponse = client().prepareSearch().setQuery(boolQuery).get();
assertHitCount(searchResponse, 0l);
boolQuery = boolQuery()
.should(termQuery("field1", "value1"))
.should(boolQuery()
.should(termQuery("field1", "value1"))
.should(termQuery("field1", "value2"))
.minimumNumberShouldMatch(3))
.minimumNumberShouldMatch(1);
searchResponse = client().prepareSearch().setQuery(boolQuery).get();
assertHitCount(searchResponse, 1l);
assertFirstHit(searchResponse, hasId("1"));
boolQuery = boolQuery()
.must(termQuery("field1", "value1"))
.must(boolQuery()
.should(termQuery("field1", "value1"))
.should(termQuery("field1", "value2"))
.minimumNumberShouldMatch(3));
searchResponse = client().prepareSearch().setQuery(boolQuery).get();
assertHitCount(searchResponse, 0l);
}
public void testFuzzyQueryString() {