Browse Source

Add support for `minimum_should_match` to `simple_query_string`

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 #6449
Lee Hinman 10 years ago
parent
commit
2e9ea4abaf

+ 5 - 0
docs/reference/query-dsl/queries/simple-query-string-query.asciidoc

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

+ 10 - 0
src/main/java/org/elasticsearch/index/query/SimpleQueryStringBuilder.java

@@ -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;
@@ -134,6 +135,11 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
         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);
@@ -186,6 +192,10 @@ public class SimpleQueryStringBuilder extends BaseQueryBuilder {
             builder.field("_name", queryName);
         }
 
+        if (minimumShouldMatch != null) {
+            builder.field("minimum_should_match", minimumShouldMatch);
+        }
+
         builder.endObject();
     }
 }

+ 9 - 0
src/main/java/org/elasticsearch/index/query/SimpleQueryStringParser.java

@@ -21,9 +21,11 @@ package org.elasticsearch.index.query;
 
 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;
@@ -89,6 +91,7 @@ public class SimpleQueryStringParser implements QueryParser {
         String queryBody = null;
         String queryName = null;
         String field = null;
+        String minimumShouldMatch = null;
         Map<String, Float> fieldsAndWeights = null;
         BooleanClause.Occur defaultOperator = null;
         Analyzer analyzer = null;
@@ -182,6 +185,8 @@ public class SimpleQueryStringParser implements QueryParser {
                     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() + "]");
                 }
@@ -221,6 +226,10 @@ public class SimpleQueryStringParser implements QueryParser {
         if (queryName != null) {
             parseContext.addNamedQuery(queryName, query);
         }
+
+        if (minimumShouldMatch != null && query instanceof BooleanQuery) {
+            Queries.applyMinimumShouldMatch((BooleanQuery) query, minimumShouldMatch);
+        }
         return query;
     }
 }

+ 48 - 0
src/test/java/org/elasticsearch/search/query/SimpleQueryStringTests.java

@@ -91,6 +91,54 @@ public class SimpleQueryStringTests extends ElasticsearchIntegrationTest {
         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");