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:
parent
1ec44dcdda
commit
4d32cc0b9f
|
@ -179,8 +179,6 @@ public class Queries {
|
||||||
result = calc < 0 ? result + calc : calc;
|
result = calc < 0 ? result + calc : calc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (optionalClauseCount < result ?
|
return result < 0 ? 0 : result;
|
||||||
optionalClauseCount : (result < 0 ? 0 : result));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,8 +273,7 @@ public class BoolQueryBuilder extends AbstractQueryBuilder<BoolQueryBuilder> {
|
||||||
return new MatchAllDocsQuery();
|
return new MatchAllDocsQuery();
|
||||||
}
|
}
|
||||||
final String minimumShouldMatch;
|
final String minimumShouldMatch;
|
||||||
if (context.isFilter() && this.minimumShouldMatch == null) {
|
if (context.isFilter() && this.minimumShouldMatch == null && shouldClauses.size() > 0) {
|
||||||
//will be applied for real only if there are should clauses
|
|
||||||
minimumShouldMatch = "1";
|
minimumShouldMatch = "1";
|
||||||
} else {
|
} else {
|
||||||
minimumShouldMatch = this.minimumShouldMatch;
|
minimumShouldMatch = this.minimumShouldMatch;
|
||||||
|
|
|
@ -254,6 +254,24 @@ public class BoolQueryBuilderTests extends AbstractQueryTestCase<BoolQueryBuilde
|
||||||
assertThat(innerBooleanClause2.getQuery(), instanceOf(MatchAllDocsQuery.class));
|
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 {
|
public void testFromJson() throws IOException {
|
||||||
String query =
|
String query =
|
||||||
"{" +
|
"{" +
|
||||||
|
|
|
@ -1016,6 +1016,59 @@ public class SearchQueryIT extends ESIntegTestCase {
|
||||||
searchResponse = client().prepareSearch().setQuery(multiMatchQuery).get();
|
searchResponse = client().prepareSearch().setQuery(multiMatchQuery).get();
|
||||||
assertHitCount(searchResponse, 1l);
|
assertHitCount(searchResponse, 1l);
|
||||||
assertFirstHit(searchResponse, hasId("1"));
|
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() {
|
public void testFuzzyQueryString() {
|
||||||
|
|
Loading…
Reference in New Issue