Browse Source

Merge pull request #15571 from jimferenczi/min_should_match

Min should match greater than the number of optional clauses should return no result
Jim Ferenczi 9 years ago
parent
commit
96e29be7c6

+ 1 - 3
core/src/main/java/org/elasticsearch/common/lucene/search/Queries.java

@@ -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;
     }
 }

+ 1 - 2
core/src/main/java/org/elasticsearch/index/query/BoolQueryBuilder.java

@@ -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;

+ 18 - 0
core/src/test/java/org/elasticsearch/index/query/BoolQueryBuilderTests.java

@@ -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 =
                 "{" +

+ 53 - 0
core/src/test/java/org/elasticsearch/search/query/SearchQueryIT.java

@@ -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() {