From c8020760d74d5a836b802ed96c016ea5e9519051 Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Thu, 14 Nov 2013 15:11:37 +0100 Subject: [PATCH] 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 --- .../index/query/MultiMatchQueryParser.java | 56 ++++++++++--------- .../query/SimpleIndexQueryParserTests.java | 16 ++++++ .../multiMatch-query-fields-as-string.json | 6 ++ .../index/query/multiMatch-query-simple.json | 6 ++ 4 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 src/test/java/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json create mode 100644 src/test/java/org/elasticsearch/index/query/multiMatch-query-simple.json diff --git a/src/main/java/org/elasticsearch/index/query/MultiMatchQueryParser.java b/src/main/java/org/elasticsearch/index/query/MultiMatchQueryParser.java index 6dc13226ac8..9f0a2d3af8b 100644 --- a/src/main/java/org/elasticsearch/index/query/MultiMatchQueryParser.java +++ b/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 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); + } + } } \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java b/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java index 9ce1d0152ea..a282bb5dc17 100644 --- a/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java +++ b/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)); + } } diff --git a/src/test/java/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json b/src/test/java/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json new file mode 100644 index 00000000000..d29211d69db --- /dev/null +++ b/src/test/java/org/elasticsearch/index/query/multiMatch-query-fields-as-string.json @@ -0,0 +1,6 @@ +{ + "multi_match": { + "query": "foo bar", + "fields": "myField" + } +} \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/index/query/multiMatch-query-simple.json b/src/test/java/org/elasticsearch/index/query/multiMatch-query-simple.json new file mode 100644 index 00000000000..904ba0e6ccb --- /dev/null +++ b/src/test/java/org/elasticsearch/index/query/multiMatch-query-simple.json @@ -0,0 +1,6 @@ +{ + "multi_match": { + "query": "foo bar", + "fields": [ "myField", "otherField" ] + } +} \ No newline at end of file