瀏覽代碼

multi_match query supports fields as single string and array

The multi_match query accepted only an array in the fields parameter. This patch allows to use a single string as well.

Also added tests for parsing in both cases.

Closes #4164
Alexander Reelsen 12 年之前
父節點
當前提交
c8020760d7

+ 31 - 25
src/main/java/org/elasticsearch/index/query/MultiMatchQueryParser.java

@@ -67,33 +67,13 @@ public class MultiMatchQueryParser implements QueryParser {
         while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
             if (token == XContentParser.Token.FIELD_NAME) {
                 currentFieldName = parser.currentName();
-            } else if (token == XContentParser.Token.START_ARRAY) {
-                if ("fields".equals(currentFieldName)) {
+            } else if ("fields".equals(currentFieldName)) {
+                if (token == XContentParser.Token.START_ARRAY) {
                     while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
-                        String fField = null;
-                        Float fBoost = null;
-                        char[] fieldText = parser.textCharacters();
-                        int end = parser.textOffset() + parser.textLength();
-                        for (int i = parser.textOffset(); i < end; i++) {
-                            if (fieldText[i] == '^') {
-                                int relativeLocation = i - parser.textOffset();
-                                fField = new String(fieldText, parser.textOffset(), relativeLocation);
-                                fBoost = Float.parseFloat(new String(fieldText, i + 1, parser.textLength() - relativeLocation - 1));
-                                break;
-                            }
-                        }
-                        if (fField == null) {
-                            fField = parser.text();
-                        }
-
-                        if (Regex.isSimpleMatchPattern(fField)) {
-                            for (String field : parseContext.mapperService().simpleMatchToIndexNames(fField)) {
-                                fieldNameWithBoosts.put(field, fBoost);
-                            }
-                        } else {
-                            fieldNameWithBoosts.put(fField, fBoost);
-                        }
+                        extractFieldAndBoost(parseContext, parser, fieldNameWithBoosts);
                     }
+                } else if (token.isValue()) {
+                    extractFieldAndBoost(parseContext, parser, fieldNameWithBoosts);
                 } else {
                     throw new QueryParsingException(parseContext.index(), "[query_string] query does not support [" + currentFieldName + "]");
                 }
@@ -184,4 +164,30 @@ public class MultiMatchQueryParser implements QueryParser {
         }
         return query;
     }
+
+    private void extractFieldAndBoost(QueryParseContext parseContext, XContentParser parser, Map<String, Float> fieldNameWithBoosts) throws IOException {
+        String fField = null;
+        Float fBoost = null;
+        char[] fieldText = parser.textCharacters();
+        int end = parser.textOffset() + parser.textLength();
+        for (int i = parser.textOffset(); i < end; i++) {
+            if (fieldText[i] == '^') {
+                int relativeLocation = i - parser.textOffset();
+                fField = new String(fieldText, parser.textOffset(), relativeLocation);
+                fBoost = Float.parseFloat(new String(fieldText, i + 1, parser.textLength() - relativeLocation - 1));
+                break;
+            }
+        }
+        if (fField == null) {
+            fField = parser.text();
+        }
+
+        if (Regex.isSimpleMatchPattern(fField)) {
+            for (String field : parseContext.mapperService().simpleMatchToIndexNames(fField)) {
+                fieldNameWithBoosts.put(field, fBoost);
+            }
+        } else {
+            fieldNameWithBoosts.put(fField, fBoost);
+        }
+    }
 }

+ 16 - 0
src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java

@@ -2268,4 +2268,20 @@ public class SimpleIndexQueryParserTests extends ElasticsearchTestCase {
         Query parsedQuery = queryParser.parse(query).query();
         assertThat((double) (parsedQuery.getBoost()), Matchers.closeTo(3.0, 1.e-7));
     }
+
+    @Test
+    public void testMultiMatchQuery() throws Exception {
+        IndexQueryParserService queryParser = queryParser();
+        String query = copyToStringFromClasspath("/org/elasticsearch/index/query/multiMatch-query-simple.json");
+        Query parsedQuery = queryParser.parse(query).query();
+        assertThat(parsedQuery, instanceOf(DisjunctionMaxQuery.class));
+    }
+
+    @Test
+    public void testMultiMatchQueryWithFieldsAsString() throws Exception {
+        IndexQueryParserService queryParser = queryParser();
+        String query = copyToStringFromClasspath("/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json");
+        Query parsedQuery = queryParser.parse(query).query();
+        assertThat(parsedQuery, instanceOf(BooleanQuery.class));
+    }
 }

+ 6 - 0
src/test/java/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json

@@ -0,0 +1,6 @@
+{
+    "multi_match": {
+        "query": "foo bar",
+        "fields": "myField"
+    }
+}

+ 6 - 0
src/test/java/org/elasticsearch/index/query/multiMatch-query-simple.json

@@ -0,0 +1,6 @@
+{
+    "multi_match": {
+        "query": "foo bar",
+        "fields": [ "myField", "otherField" ]
+    }
+}