diff --git a/docs/reference/query-languages/esql/_snippets/functions/examples/match.md b/docs/reference/query-languages/esql/_snippets/functions/examples/match.md index 78b0eb5dfc0d2..0758e92f98180 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/examples/match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/examples/match.md @@ -4,7 +4,10 @@ ```esql FROM books -| WHERE MATCH(author, "Faulkner") +| WHERE MULTI_MATCH(author, description, "Faulkner") +| KEEP book_no, author +| SORT book_no +| LIMIT 5 ``` | book_no:keyword | author:text | @@ -17,7 +20,7 @@ FROM books ```esql FROM books -| WHERE MATCH(title, "Hobbit Back Again", {"operator": "AND"}) +| WHERE MULTI_MATCH(title, description, "Hobbit Back Again", {"operator": "AND"}) | KEEP title; ``` diff --git a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/match.md b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/match.md index 82d98ee1b1ea2..d765f9b66de9d 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/functionNamedParams/match.md @@ -8,29 +8,20 @@ `auto_generate_synonyms_phrase_query` : (boolean) If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true. -`analyzer` -: (keyword) Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used. - `minimum_should_match` : (integer) Minimum number of clauses that must match for a document to be returned. -`zero_terms_query` -: (keyword) Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none. - -`boost` -: (float) Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0. - `fuzzy_transpositions` : (boolean) If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true. -`fuzzy_rewrite` -: (keyword) Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default. +`tie_breaker` +: (float) Controls how score is blended together between field groups. Defaults to 0 (best score from each group). -`prefix_length` -: (integer) Number of beginning characters left unchanged for fuzzy matching. Defaults to 0. +`type` +: (object) Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>. `lenient` -: (boolean) If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false. +: (boolean) If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true. `operator` : (keyword) Boolean logic used to interpret text in the query value. Defaults to OR. @@ -38,3 +29,18 @@ `max_expansions` : (integer) Maximum number of terms to which the query will expand. Defaults to 50. +`analyzer` +: (keyword) Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used. + +`zero_terms_query` +: (keyword) Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none. + +`boost` +: (float) Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0. + +`fuzzy_rewrite` +: (keyword) Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default. + +`prefix_length` +: (integer) Number of beginning characters left unchanged for fuzzy matching. Defaults to 0. + diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/match.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/match.md index c3f229589e9c6..5b63fe89507e1 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/match.md @@ -2,11 +2,11 @@ **Parameters** -`field` -: Field that the query will target. +`fields` +: Fields to use for matching `query` -: Value to find in the provided field. +: Value to find in the provided fields. `options` : (Optional) Match additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/multi_match.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/multi_match.md index 28b61d60de534..500e59c0bbd1e 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/multi_match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/multi_match.md @@ -2,12 +2,12 @@ **Parameters** -`query` -: Value to find in the provided fields. - `fields` : Fields to use for matching +`query` +: Value to find in the provided fields. + `options` : (Optional) Additional options for MultiMatch, passed as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params)." See [multi-match query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-multi-match-query) for more information. diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/match.md b/docs/reference/query-languages/esql/_snippets/functions/types/match.md index a9379ab5ac226..9767794bb1074 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/match.md @@ -2,7 +2,7 @@ **Supported types** -| field | query | options | result | +| fields | query | options | result | | --- | --- | --- | --- | | boolean | boolean | named parameters | boolean | | boolean | keyword | named parameters | boolean | diff --git a/docs/reference/query-languages/esql/_snippets/functions/types/multi_match.md b/docs/reference/query-languages/esql/_snippets/functions/types/multi_match.md index cdaf9eb630cec..9767794bb1074 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/types/multi_match.md +++ b/docs/reference/query-languages/esql/_snippets/functions/types/multi_match.md @@ -2,7 +2,7 @@ **Supported types** -| query | fields | options | result | +| fields | query | options | result | | --- | --- | --- | --- | | boolean | boolean | named parameters | boolean | | boolean | keyword | named parameters | boolean | diff --git a/docs/reference/query-languages/esql/images/functions/match.svg b/docs/reference/query-languages/esql/images/functions/match.svg index d3e5c362a1a74..a902905ffe003 100644 --- a/docs/reference/query-languages/esql/images/functions/match.svg +++ b/docs/reference/query-languages/esql/images/functions/match.svg @@ -1 +1 @@ -MATCH(field,query,options) \ No newline at end of file +MATCH(,fields,query,options) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/images/functions/multi_match.svg b/docs/reference/query-languages/esql/images/functions/multi_match.svg index 93e27774b2c63..423522a0b0397 100644 --- a/docs/reference/query-languages/esql/images/functions/multi_match.svg +++ b/docs/reference/query-languages/esql/images/functions/multi_match.svg @@ -1 +1 @@ -MULTI_MATCH(query,fields,options) \ No newline at end of file +MULTI_MATCH(,fields,query,options) \ No newline at end of file diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/match.json b/docs/reference/query-languages/esql/kibana/definition/functions/match.json index e00c20d8819fc..c9d447fe93849 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/match.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/match.json @@ -7,732 +7,732 @@ { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "boolean", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "boolean", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "boolean", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "date", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "date", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "date", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "date_nanos", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "date_nanos", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "date_nanos", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "double", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "long", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "double", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "long", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "ip", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "ip", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "ip", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "keyword", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "double", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "long", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "text", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "double", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "long", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "version", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" }, { "params" : [ { - "name" : "field", + "name" : "fields", "type" : "version", "optional" : false, - "description" : "Field that the query will target." + "description" : "Fields to use for matching" }, { "name" : "query", "type" : "version", "optional" : false, - "description" : "Value to find in the provided field." + "description" : "Value to find in the provided fields." }, { "name" : "options", "type" : "function_named_parameters", - "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to false.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}", + "mapParams" : "{name='fuzziness', values=[AUTO, 1, 2], description='Maximum edit distance allowed for matching.'}, {name='auto_generate_synonyms_phrase_query', values=[true, false], description='If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true.'}, {name='minimum_should_match', values=[2], description='Minimum number of clauses that must match for a document to be returned.'}, {name='fuzzy_transpositions', values=[true, false], description='If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). Defaults to true.'}, {name='tie_breaker', values=[0], description='Controls how score is blended together between field groups. Defaults to 0 (best score from each group).'}, {name='type', values=['best_fields'], description='Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, `cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. See <>.'}, {name='lenient', values=[true, false], description='If false, format-based errors, such as providing a text query value for a numeric field, are returned. Defaults to true.'}, {name='operator', values=[AND, OR], description='Boolean logic used to interpret text in the query value. Defaults to OR.'}, {name='max_expansions', values=[50], description='Maximum number of terms to which the query will expand. Defaults to 50.'}, {name='analyzer', values=[standard], description='Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer mapped for the field. If no analyzer is mapped, the index’s default analyzer is used.'}, {name='zero_terms_query', values=[none, all], description='Indicates whether all documents or none are returned if the analyzer removes all tokens, such as when using a stop filter. Defaults to none.'}, {name='boost', values=[2.5], description='Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0.'}, {name='fuzzy_rewrite', values=[constant_score_blended, constant_score, constant_score_boolean, top_terms_blended_freqs_N, top_terms_boost_N, top_terms_N], description='Method used to rewrite the query. See the rewrite parameter for valid values and more information. If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of top_terms_blended_freqs_${max_expansions} by default.'}, {name='prefix_length', values=[1], description='Number of beginning characters left unchanged for fuzzy matching. Defaults to 0.'}", "optional" : true, "description" : "(Optional) Match additional options as <>." } ], - "variadic" : false, + "variadic" : true, "returnType" : "boolean" } ], "examples" : [ - "FROM books\n| WHERE MATCH(author, \"Faulkner\")", - "FROM books\n| WHERE MATCH(title, \"Hobbit Back Again\", {\"operator\": \"AND\"})\n| KEEP title;" + "FROM books\n| WHERE MULTI_MATCH(author, description, \"Faulkner\")\n| KEEP book_no, author\n| SORT book_no\n| LIMIT 5", + "FROM books\n| WHERE MULTI_MATCH(title, description, \"Hobbit Back Again\", {\"operator\": \"AND\"})\n| KEEP title;" ], "preview" : false, "snapshot_only" : false diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/multi_match.json b/docs/reference/query-languages/esql/kibana/definition/functions/multi_match.json index 90539229c3d25..160c69bc5b067 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/multi_match.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/multi_match.json @@ -7,16 +7,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "boolean", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "boolean", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -32,16 +32,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "boolean", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -57,16 +57,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "date", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "date", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -82,16 +82,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "date", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -107,16 +107,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "date_nanos", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "date_nanos", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -132,16 +132,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "date_nanos", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -157,16 +157,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "double", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -182,16 +182,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "integer", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -207,16 +207,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -232,16 +232,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "double", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "long", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -257,16 +257,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "double", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -282,16 +282,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "integer", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -307,16 +307,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -332,16 +332,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "integer", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "long", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -357,16 +357,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "ip", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "ip", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -382,16 +382,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "ip", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -407,16 +407,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "keyword", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -432,16 +432,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "double", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -457,16 +457,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "integer", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -482,16 +482,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -507,16 +507,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "long", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -532,16 +532,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "text", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -557,16 +557,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "double", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -582,16 +582,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "integer", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -607,16 +607,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -632,16 +632,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "long", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -657,16 +657,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "unsigned_long", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "unsigned_long", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -682,16 +682,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "version", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "keyword", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", @@ -707,16 +707,16 @@ { "params" : [ { - "name" : "query", + "name" : "fields", "type" : "version", "optional" : false, - "description" : "Value to find in the provided fields." + "description" : "Fields to use for matching" }, { - "name" : "fields", + "name" : "query", "type" : "version", "optional" : false, - "description" : "Fields to use for matching" + "description" : "Value to find in the provided fields." }, { "name" : "options", diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/match.md b/docs/reference/query-languages/esql/kibana/docs/functions/match.md index 116edb0cb37b5..f6557573c5d6e 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/match.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/match.md @@ -6,5 +6,5 @@ Using `MATCH` is equivalent to using the `match` query in the Elasticsearch Quer ```esql FROM books -| WHERE MATCH(author, "Faulkner") +| WHERE MATCH(author, description, "Faulkner") ``` diff --git a/server/src/main/java/org/elasticsearch/index/query/MultiFieldMatchQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/MultiFieldMatchQueryBuilder.java new file mode 100644 index 0000000000000..82940760f6281 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/query/MultiFieldMatchQueryBuilder.java @@ -0,0 +1,374 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.query; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.similarities.BM25Similarity; +import org.apache.lucene.search.similarities.Similarity; +import org.elasticsearch.TransportVersion; +import org.elasticsearch.TransportVersions; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.lucene.search.Queries; +import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.TextFieldMapper; +import org.elasticsearch.index.search.QueryParserHelper; +import org.elasticsearch.lucene.similarity.LegacyBM25Similarity; +import org.elasticsearch.xcontent.ConstructingObjectParser; +import org.elasticsearch.xcontent.ObjectParser; +import org.elasticsearch.xcontent.ParseField; +import org.elasticsearch.xcontent.XContentBuilder; +import org.elasticsearch.xcontent.XContentParser; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +/** + * A query builder similar to MultiMatchQueryBuilder, but not exposed for external use, and translating to a combined query. + */ +public class MultiFieldMatchQueryBuilder extends AbstractQueryBuilder { + + public static final String NAME = "multi_field_match"; + + public static final ParseField QUERY_FIELD = new ParseField("query"); + public static final ParseField FIELDS_FIELD = new ParseField("fields"); + public static final ParseField OPERATOR_FIELD = new ParseField("operator"); + public static final ParseField MINIMUM_SHOULD_MATCH_FIELD = new ParseField("minimum_should_match"); + public static final ParseField GENERATE_SYNONYMS_PHRASE_QUERY = new ParseField("auto_generate_synonyms_phrase_query"); + public static final ParseField ZERO_TERMS_QUERY_FIELD = new ParseField("zero_terms_query"); + + private static final Operator DEFAULT_OPERATOR = Operator.AND; + private static final ZeroTermsQueryOption DEFAULT_ZERO_TERMS_QUERY = ZeroTermsQueryOption.NONE; + private static final boolean DEFAULT_GENERATE_SYNONYMS_PHRASE = true; + + private final Object value; + private final Map fieldsAndBoosts; + private Operator operator = DEFAULT_OPERATOR; + private String minimumShouldMatch; + private ZeroTermsQueryOption zeroTermsQuery = DEFAULT_ZERO_TERMS_QUERY; + private boolean autoGenerateSynonymsPhraseQuery = DEFAULT_GENERATE_SYNONYMS_PHRASE; + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( + NAME, + a -> new MultiFieldMatchQueryBuilder(a[0]) + ); + + static { + PARSER.declareString(ConstructingObjectParser.constructorArg(), QUERY_FIELD); + PARSER.declareStringArray((builder, values) -> { + Map fieldsAndBoosts = QueryParserHelper.parseFieldsAndWeights(values); + builder.fields(fieldsAndBoosts); + }, FIELDS_FIELD); + + PARSER.declareString(MultiFieldMatchQueryBuilder::operator, Operator::fromString, OPERATOR_FIELD); + PARSER.declareField( + MultiFieldMatchQueryBuilder::minimumShouldMatch, + XContentParser::textOrNull, + MINIMUM_SHOULD_MATCH_FIELD, + // using INT_OR_NULL (which includes VALUE_NUMBER, VALUE_STRING, VALUE_NULL) to also allow for numeric values and null + ObjectParser.ValueType.INT_OR_NULL + ); + PARSER.declareBoolean(MultiFieldMatchQueryBuilder::autoGenerateSynonymsPhraseQuery, GENERATE_SYNONYMS_PHRASE_QUERY); + PARSER.declareString(MultiFieldMatchQueryBuilder::zeroTermsQuery, value -> { + if ("none".equalsIgnoreCase(value)) { + return ZeroTermsQueryOption.NONE; + } else if ("all".equalsIgnoreCase(value)) { + return ZeroTermsQueryOption.ALL; + } else { + throw new IllegalArgumentException("Unsupported [" + ZERO_TERMS_QUERY_FIELD.getPreferredName() + "] value [" + value + "]"); + } + }, ZERO_TERMS_QUERY_FIELD); + + PARSER.declareFloat(MultiFieldMatchQueryBuilder::boost, BOOST_FIELD); + PARSER.declareString(MultiFieldMatchQueryBuilder::queryName, NAME_FIELD); + } + + /** + * Constructs a new text query. + */ + private MultiFieldMatchQueryBuilder(Object value) { + if (value == null) { + throw new IllegalArgumentException("[" + NAME + "] requires query value"); + } + this.value = value; + this.fieldsAndBoosts = new TreeMap<>(); + } + + public static MultiFieldMatchQueryBuilder create(Object value, String... fields) { + if (fields == null) { + throw new IllegalArgumentException("[" + NAME + "] requires field list"); + } + var result = new MultiFieldMatchQueryBuilder(value); + for (String field : fields) { + result = result.field(field); + } + return result; + } + + /** + * Read from a stream. + */ + public MultiFieldMatchQueryBuilder(StreamInput in) throws IOException { + super(in); + value = in.readGenericValue(); + int size = in.readVInt(); + fieldsAndBoosts = new TreeMap<>(); + for (int i = 0; i < size; i++) { + String field = in.readString(); + float boost = in.readFloat(); + fieldsAndBoosts.put(field, boost); + } + operator = Operator.readFromStream(in); + minimumShouldMatch = in.readOptionalString(); + zeroTermsQuery = ZeroTermsQueryOption.readFromStream(in); + autoGenerateSynonymsPhraseQuery = in.readBoolean(); + } + + @Override + protected void doWriteTo(StreamOutput out) throws IOException { + out.writeGenericValue(value); + out.writeVInt(fieldsAndBoosts.size()); + for (Map.Entry fieldsEntry : fieldsAndBoosts.entrySet()) { + out.writeString(fieldsEntry.getKey()); + out.writeFloat(fieldsEntry.getValue()); + } + operator.writeTo(out); + out.writeOptionalString(minimumShouldMatch); + zeroTermsQuery.writeTo(out); + out.writeBoolean(autoGenerateSynonymsPhraseQuery); + } + + /** + * Adds a field to run the query against. + */ + public MultiFieldMatchQueryBuilder field(String field) { + if (Strings.isEmpty(field)) { + throw new IllegalArgumentException("supplied field is null or empty."); + } + this.fieldsAndBoosts.put(field, AbstractQueryBuilder.DEFAULT_BOOST); + return this; + } + + /** + * Adds a field to run the query against with a specific boost. + */ + public MultiFieldMatchQueryBuilder field(String field, float boost) { + if (Strings.isEmpty(field)) { + throw new IllegalArgumentException("supplied field is null or empty."); + } + validateFieldBoost(boost); + this.fieldsAndBoosts.put(field, boost); + return this; + } + + /** + * Add several fields to run the query against with a specific boost. + */ + public MultiFieldMatchQueryBuilder fields(Map fields) { + for (float fieldBoost : fields.values()) { + validateFieldBoost(fieldBoost); + } + this.fieldsAndBoosts.putAll(fields); + return this; + } + + public Map fields() { + return fieldsAndBoosts; + } + + /** + * Sets the operator to use for the top-level boolean query. Defaults to {@code OR}. + */ + public MultiFieldMatchQueryBuilder operator(Operator operator) { + if (operator == null) { + throw new IllegalArgumentException("[" + NAME + "] requires operator to be non-null"); + } + this.operator = operator; + return this; + } + + public Operator operator() { + return operator; + } + + public MultiFieldMatchQueryBuilder minimumShouldMatch(String minimumShouldMatch) { + this.minimumShouldMatch = minimumShouldMatch; + return this; + } + + public String minimumShouldMatch() { + return minimumShouldMatch; + } + + public MultiFieldMatchQueryBuilder zeroTermsQuery(ZeroTermsQueryOption zeroTermsQuery) { + if (zeroTermsQuery == null) { + throw new IllegalArgumentException("[" + NAME + "] requires zero terms query to be non-null"); + } + this.zeroTermsQuery = zeroTermsQuery; + return this; + } + + public MultiFieldMatchQueryBuilder autoGenerateSynonymsPhraseQuery(boolean enable) { + this.autoGenerateSynonymsPhraseQuery = enable; + return this; + } + + private static void validateFieldBoost(float boost) { + if (boost < 1.0f) { + throw new IllegalArgumentException("[" + NAME + "] requires field boosts to be >= 1.0"); + } + } + + @Override + public void doXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(NAME); + builder.field(QUERY_FIELD.getPreferredName(), value); + builder.startArray(FIELDS_FIELD.getPreferredName()); + for (Map.Entry fieldEntry : this.fieldsAndBoosts.entrySet()) { + builder.value(fieldEntry.getKey() + "^" + fieldEntry.getValue()); + } + builder.endArray(); + if (operator != DEFAULT_OPERATOR) { + builder.field(OPERATOR_FIELD.getPreferredName(), operator.toString()); + } + if (minimumShouldMatch != null) { + builder.field(MINIMUM_SHOULD_MATCH_FIELD.getPreferredName(), minimumShouldMatch); + } + if (zeroTermsQuery != DEFAULT_ZERO_TERMS_QUERY) { + builder.field(ZERO_TERMS_QUERY_FIELD.getPreferredName(), zeroTermsQuery.toString()); + } + if (autoGenerateSynonymsPhraseQuery != DEFAULT_GENERATE_SYNONYMS_PHRASE) { + builder.field(GENERATE_SYNONYMS_PHRASE_QUERY.getPreferredName(), autoGenerateSynonymsPhraseQuery); + } + boostAndQueryNameToXContent(builder); + builder.endObject(); + } + + public static MultiFieldMatchQueryBuilder fromXContent(XContentParser parser) throws IOException { + return PARSER.parse(parser, null); + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + protected Query doToQuery(SearchExecutionContext context) throws IOException { + if (fieldsAndBoosts.isEmpty()) { + throw new IllegalArgumentException("In [" + NAME + "] query, at least one field must be provided"); + } + + Map fields = QueryParserHelper.resolveMappingFields(context, fieldsAndBoosts); + // If all fields are unmapped, then return an 'unmapped field query'. + boolean hasMappedField = fields.keySet().stream().anyMatch(k -> context.getFieldType(k) != null); + if (hasMappedField == false) { + return Queries.newUnmappedFieldsQuery(fields.keySet()); + } + + validateSimilarity(context, fields); + + Map> groups = new HashMap<>(); + for (Map.Entry entry : fields.entrySet()) { + String name = entry.getKey(); + MappedFieldType fieldType = context.getFieldType(name); + if (fieldType == null) { + continue; + } + + if (fieldType.familyTypeName().equals(TextFieldMapper.CONTENT_TYPE) == false) { + throw new IllegalArgumentException( + "Field [" + fieldType.name() + "] of type [" + fieldType.typeName() + "] does not support [" + NAME + "] queries" + ); + } + + // TODO: handle per-field boosts. + + Analyzer analyzer = fieldType.getTextSearchInfo().searchAnalyzer(); + if (groups.containsKey(analyzer) == false) { + groups.put(analyzer, new ArrayList<>()); + } + groups.get(analyzer).add(name); + } + + // TODO: For now assume we have one group. + assert groups.size() == 1; + + var disMax = new DisMaxQueryBuilder(); + for (Map.Entry> group : groups.entrySet()) { + /* + TODO + String placeholderFieldName = fieldsAndBoosts.get(0).fieldType.name(); + boolean canGenerateSynonymsPhraseQuery = autoGenerateSynonymsPhraseQuery; + for (FieldAndBoost fieldAndBoost : fieldsAndBoosts) { + TextSearchInfo textSearchInfo = fieldAndBoost.fieldType.getTextSearchInfo(); + canGenerateSynonymsPhraseQuery &= textSearchInfo.hasPositions(); + } + */ + + var combinedFields = new CombinedFieldsQueryBuilder(value, group.getValue().toArray(new String[0])); + combinedFields = combinedFields.operator(operator); + disMax.add(combinedFields); + } + + /* + TODO + Query query = disMax.createBooleanQuery(placeholderFieldName, value.toString(), operator.toBooleanClauseOccur()); + query = Queries.maybeApplyMinimumShouldMatch(query, minimumShouldMatch); + if (query == null) { + query = zeroTermsQuery.asQuery(); + } + + */ + return disMax.doToQuery(context); + } + + private static void validateSimilarity(SearchExecutionContext context, Map fields) { + for (Map.Entry entry : fields.entrySet()) { + String name = entry.getKey(); + MappedFieldType fieldType = context.getFieldType(name); + if (fieldType != null && fieldType.getTextSearchInfo().similarity() != null) { + throw new IllegalArgumentException("[" + NAME + "] queries cannot be used with per-field similarities"); + } + } + + Similarity defaultSimilarity = context.getDefaultSimilarity(); + if ((defaultSimilarity instanceof LegacyBM25Similarity || defaultSimilarity instanceof BM25Similarity) == false) { + throw new IllegalArgumentException("[" + NAME + "] queries can only be used with the [BM25] similarity"); + } + } + + @Override + protected int doHashCode() { + return Objects.hash(value, fieldsAndBoosts, operator, minimumShouldMatch, zeroTermsQuery, autoGenerateSynonymsPhraseQuery); + } + + @Override + protected boolean doEquals(MultiFieldMatchQueryBuilder other) { + return Objects.equals(value, other.value) + && Objects.equals(fieldsAndBoosts, other.fieldsAndBoosts) + && Objects.equals(operator, other.operator) + && Objects.equals(minimumShouldMatch, other.minimumShouldMatch) + && Objects.equals(zeroTermsQuery, other.zeroTermsQuery) + && Objects.equals(autoGenerateSynonymsPhraseQuery, other.autoGenerateSynonymsPhraseQuery); + } + + @Override + public TransportVersion getMinimalSupportedVersion() { + return TransportVersions.ZERO; + } +} diff --git a/server/src/main/java/org/elasticsearch/index/query/QueryBuilders.java b/server/src/main/java/org/elasticsearch/index/query/QueryBuilders.java index 66f1c9a74d4c2..e47b25a1b524c 100644 --- a/server/src/main/java/org/elasticsearch/index/query/QueryBuilders.java +++ b/server/src/main/java/org/elasticsearch/index/query/QueryBuilders.java @@ -60,6 +60,14 @@ public static MultiMatchQueryBuilder multiMatchQuery(Object text, String... fiel return new MultiMatchQueryBuilder(text, fieldNames); // BOOLEAN is the default } + /** + * Creates a query builder for match with multiple fields (distinct from multi-match). + * TODO: better comment. + */ + public static MultiFieldMatchQueryBuilder multiFieldMatchQuery(Object text, String... fieldNames) { + return MultiFieldMatchQueryBuilder.create(text, fieldNames); + } + /** * Creates a text query with type "BOOL_PREFIX" for the provided field name and text. * diff --git a/server/src/main/java/org/elasticsearch/search/SearchModule.java b/server/src/main/java/org/elasticsearch/search/SearchModule.java index 56b203700b362..184ea69aad0c3 100644 --- a/server/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/server/src/main/java/org/elasticsearch/search/SearchModule.java @@ -44,6 +44,7 @@ import org.elasticsearch.index.query.MatchPhraseQueryBuilder; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.MoreLikeThisQueryBuilder; +import org.elasticsearch.index.query.MultiFieldMatchQueryBuilder; import org.elasticsearch.index.query.MultiMatchQueryBuilder; import org.elasticsearch.index.query.NestedQueryBuilder; import org.elasticsearch.index.query.PrefixQueryBuilder; @@ -1137,6 +1138,9 @@ private void registerQueryParsers(List plugins) { registerQuery(new QuerySpec<>(SpanNearQueryBuilder.NAME, SpanNearQueryBuilder::new, SpanNearQueryBuilder::fromXContent)); registerQuery(new QuerySpec<>(SpanGapQueryBuilder.NAME, SpanGapQueryBuilder::new, SpanGapQueryBuilder::fromXContent)); registerQuery(new QuerySpec<>(SpanOrQueryBuilder.NAME, SpanOrQueryBuilder::new, SpanOrQueryBuilder::fromXContent)); + namedWriteables.add( + new NamedWriteableRegistry.Entry(QueryBuilder.class, MultiFieldMatchQueryBuilder.NAME, MultiFieldMatchQueryBuilder::new) + ); registerQuery( new QuerySpec<>(MoreLikeThisQueryBuilder.NAME, MoreLikeThisQueryBuilder::new, MoreLikeThisQueryBuilder::fromXContent) ); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/multi-match-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/multi-match-function.csv-spec index a821cfca93585..6fcede9433dc5 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/multi-match-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/multi-match-function.csv-spec @@ -3,11 +3,11 @@ # multiMatchWithField -required_capability: multi_match_function +required_capability: multi_match_unified_function // tag::multi-match-with-field[] FROM books -| WHERE MULTI_MATCH("Faulkner", author, description) +| WHERE MATCH(author, description, "Faulkner") | KEEP book_no, author | SORT book_no | LIMIT 5 @@ -24,33 +24,12 @@ book_no:keyword | author:text // end::multi-match-with-field-result[] ; -testMultiMatchWithOptionsFuzziness -required_capability: multi_match_function - -from books -| where multi_match("Pings", title, description, {"fuzziness": 1}) -| keep book_no; -ignoreOrder:true - -book_no:keyword -1463 -2675 -2714 -2936 -4023 -4917 -5335 -7140 -7350 -8875 -; - testMultiMatchWithOptionsOperator -required_capability: multi_match_function +required_capability: multi_match_unified_function // tag::multi-match-with-named-function-params[] FROM books -| WHERE MULTI_MATCH("Hobbit Back Again", title, description, {"operator": "AND"}) +| WHERE MATCH(title, description, "Hobbit Back Again", {"operator": "AND"}) | KEEP title; // end::multi-match-with-named-function-params[] @@ -61,24 +40,23 @@ The Hobbit or There and Back Again ; testMultiMatchWithOptionsMinimumShouldMatch -required_capability: multi_match_function +required_capability: multi_match_unified_function from books -| where multi_match("here back again", title, description, {"minimum_should_match": 2, "operator": "OR"}) +| where match(title, description, "there back again", {"minimum_should_match": 2, "operator": "AND"}) | sort book_no | keep title; title:text -My First 100 Words in Spanish/English (My First 100 Words Pull-Tab Book) The Hobbit or There and Back Again ; testMultiMatchWithNonPushableDisjunctions -required_capability: multi_match_function +required_capability: multi_match_unified_function required_capability: full_text_functions_disjunctions_compute_engine from books -| where multi_match("lord", title, description) or length(title) > 130 +| where match(title, description, "lord") or length(title) > 130 | keep book_no ; ignoreOrder: true @@ -95,39 +73,3 @@ book_no:keyword 8678 8875 ; - -testMultiMatchPhraseQuery -required_capability: multi_match_function - -from books -| where multi_match("Lord of the rings", title, description, { "type": "phrase" } ) -| keep title -; -ignoreOrder: true - -title:text -A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings -Return of the Shadow -The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) -Letters of J R R Tolkien -The Lord of the Rings - Boxed Set -The Two Towers -Realms of Tolkien: Images of Middle-earth -Return of the King Being the Third Part of The Lord of the Rings -; - -testMultiMatchPhrasePrefixQuery -required_capability: multi_match_function - -from books -| where multi_match("Lord of the ri", title, { "type": "phrase_prefix" } ) -| keep title -; -ignoreOrder: true - -title:text -The Lord of the Rings - Boxed Set -Return of the King Being the Third Part of The Lord of the Rings -A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings -The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) -; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec index 2ae56c643b836..f3486daf27cb8 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/scoring.csv-spec @@ -115,24 +115,24 @@ book_no:keyword | title:text ; testMultiMatchWithScore -required_capability: multi_match_function +required_capability: multi_match_unified_function required_capability: metadata_score from books metadata _score -| where multi_match("Mark", author, title, {"fuzziness": 1}) +| where match(author, title, "Stranger", {"operator": "OR"}) | keep book_no, title, author, _score; ignoreOrder:true book_no:keyword | title:text | author:text | _score:double -2847 | To Love A Dark Stranger (Lovegram Historical Romance) | Colleen Faulkner | 1.9662091732025146 +2847 | To Love A Dark Stranger (Lovegram Historical Romance) | Colleen Faulkner | 2.8462226390838623 ; testMultiMatchWithScore1 -required_capability: multi_match_function +required_capability: multi_match_unified_function required_capability: metadata_score from books metadata _score -| where multi_match("Hobbit", description, title, {"type": "best_fields"}) +| where match(description, title, "Hobbit", {"operator": "AND"}) | sort book_no | eval _score = round(_score) | keep book_no, _score; @@ -155,11 +155,11 @@ book_no:keyword | _score:double ; testMultiMatchWithScore2 -required_capability: multi_match_function +required_capability: multi_match_unified_function required_capability: metadata_score from books metadata _score -| where multi_match("Hobbit", description, title, {"type": "most_fields"}) +| where match(description, title, "Hobbit", {"operator": "AND"}) | sort book_no | eval _score = round(_score) | keep book_no, _score; @@ -172,7 +172,7 @@ book_no:keyword | _score:double 2714 | 2.0 2936 | 1.0 4023 | 2.0 -4289 | 6.0 +4289 | 3.0 5335 | 2.0 5996 | 2.0 6405 | 2.0 diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchFunctionIT.java index 23958fcd35f30..b77b2b5358b87 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchFunctionIT.java @@ -87,7 +87,7 @@ public void testMultipleWhereMatch() { """; var error = expectThrows(ElasticsearchException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("[MATCH] function cannot be used after LIMIT")); + assertThat(error.getMessage(), containsString("[Match] function cannot be used after LIMIT")); } public void testNotWhereMatch() { @@ -190,7 +190,7 @@ public void testWhereMatchEvalColumn() { var error = expectThrows(VerificationException.class, () -> run(query)); assertThat( error.getMessage(), - containsString("[MATCH] function cannot operate on [upper_content], which is not a field from an index mapping") + containsString("[Match] function cannot operate on [upper_content], which is not a field from an index mapping") ); } @@ -205,7 +205,7 @@ public void testWhereMatchOverWrittenColumn() { var error = expectThrows(VerificationException.class, () -> run(query)); assertThat( error.getMessage(), - containsString("[MATCH] function cannot operate on [content], which is not a field from an index mapping") + containsString("[Match] function cannot operate on [content], which is not a field from an index mapping") ); } @@ -244,7 +244,7 @@ public void testWhereMatchWithRow() { var error = expectThrows(ElasticsearchException.class, () -> run(query)); assertThat( error.getMessage(), - containsString("line 2:15: [MATCH] function cannot operate on [content], which is not a field from an index mapping") + containsString("line 2:15: [Match] function cannot operate on [content], which is not a field from an index mapping") ); } @@ -255,7 +255,7 @@ public void testMatchWithStats() { """; var error = expectThrows(ElasticsearchException.class, () -> run(errorQuery)); - assertThat(error.getMessage(), containsString("[MATCH] function is only supported in WHERE and STATS commands")); + assertThat(error.getMessage(), containsString("[Match] function is only supported in WHERE and STATS commands")); var query = """ FROM test @@ -291,7 +291,7 @@ public void testMatchWithinEval() { """; var error = expectThrows(VerificationException.class, () -> run(query)); - assertThat(error.getMessage(), containsString("[MATCH] function is only supported in WHERE and STATS commands")); + assertThat(error.getMessage(), containsString("[Match] function is only supported in WHERE and STATS commands")); } private void createAndPopulateIndex() { diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java index f6d27bcb628f0..3988eba279354 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/ScoringIT.java @@ -46,7 +46,6 @@ protected Collection> nodePlugins() { public static List params() { List params = new ArrayList<>(); params.add(new Object[] { "match(content, \"fox\")" }); - params.add(new Object[] { "multi_match(\"fox\", content, {\"operator\": \"AND\"})" }); params.add(new Object[] { "content:\"fox\"" }); params.add(new Object[] { "qstr(\"content: fox\")" }); params.add(new Object[] { "kql(\"content*: fox\")" }); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 9a8b71e8e5eea..9d0a1fb10a2ec 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -953,6 +953,11 @@ public enum Cap { */ MULTI_MATCH_FUNCTION(Build.current().isSnapshot()), + /** + * Support for unified match and multi-match functions. + */ + MULTI_MATCH_UNIFIED_FUNCTION(Build.current().isSnapshot()), + /** * Do {@code TO_LOWER} and {@code TO_UPPER} process all field values? */ diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index bf6affb49a0b2..d9dc2d777d3f9 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -47,7 +47,6 @@ import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchPhrase; -import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.fulltext.Term; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; @@ -455,11 +454,9 @@ private static FunctionDefinition[][] functions() { // fulltext functions new FunctionDefinition[] { def(Kql.class, uni(Kql::new), "kql"), - def(Match.class, tri(Match::new), "match"), - def(MultiMatch.class, MultiMatch::new, "multi_match"), + def(Match.class, Match::new, "match"), def(QueryString.class, bi(QueryString::new), "qstr"), def(MatchPhrase.class, tri(MatchPhrase::new), "match_phrase") } }; - } private static FunctionDefinition[][] snapshotFunctions() { @@ -1076,7 +1073,7 @@ protected interface UnaryVariadicBuilder { } protected interface BinaryVariadicWithOptionsBuilder { - T build(Source source, Expression exp, List variadic, Expression options); + T build(Source source, List variadic, Expression exp, Expression options); }; protected static FunctionDefinition def( @@ -1093,10 +1090,10 @@ protected static FunctionDefinition def( } Expression options = children.getLast(); if (options instanceof MapExpression) { - return ctorRef.build(source, children.get(0), children.subList(1, children.size() - 1), options); + return ctorRef.build(source, children.subList(0, children.size() - 2), children.get(children.size() - 2), options); } - return ctorRef.build(source, children.get(0), children.subList(1, children.size()), null); + return ctorRef.build(source, children.subList(0, children.size() - 1), children.getLast(), null); }; return def(function, builder, names); } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index 18c0a22589baa..eb11154eb4fb8 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -21,7 +21,6 @@ public static List getNamedWriteables() { entries.add(QueryString.ENTRY); entries.add(Match.ENTRY); - entries.add(MultiMatch.ENTRY); entries.add(Kql.ENTRY); entries.add(MatchPhrase.ENTRY); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java index 53aa87f4b861a..1a5c59801f78d 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Match.java @@ -8,18 +8,16 @@ package org.elasticsearch.xpack.esql.expression.function.fulltext; import org.apache.lucene.util.BytesRef; -import org.elasticsearch.TransportVersions; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.unit.Fuzziness; +import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.xpack.esql.capabilities.PostAnalysisPlanVerificationAware; import org.elasticsearch.xpack.esql.common.Failure; import org.elasticsearch.xpack.esql.common.Failures; import org.elasticsearch.xpack.esql.core.InvalidArgumentException; import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.FoldContext; import org.elasticsearch.xpack.esql.core.expression.MapExpression; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; @@ -39,6 +37,7 @@ import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.esql.planner.TranslatorHandler; import org.elasticsearch.xpack.esql.querydsl.query.MatchQuery; +import org.elasticsearch.xpack.esql.querydsl.query.MultiMatchQuery; import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter; import java.io.IOException; @@ -48,19 +47,24 @@ import java.util.Objects; import java.util.Set; import java.util.function.BiConsumer; +import java.util.stream.Stream; import static java.util.Map.entry; -import static org.elasticsearch.index.query.AbstractQueryBuilder.BOOST_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.ANALYZER_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.FUZZY_REWRITE_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.FUZZY_TRANSPOSITIONS_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.GENERATE_SYNONYMS_PHRASE_QUERY; -import static org.elasticsearch.index.query.MatchQueryBuilder.LENIENT_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.MAX_EXPANSIONS_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.MINIMUM_SHOULD_MATCH_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.OPERATOR_FIELD; -import static org.elasticsearch.index.query.MatchQueryBuilder.PREFIX_LENGTH_FIELD; import static org.elasticsearch.index.query.MatchQueryBuilder.ZERO_TERMS_QUERY_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.ANALYZER_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.BOOST_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZINESS_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_REWRITE_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_TRANSPOSITIONS_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.GENERATE_SYNONYMS_PHRASE_QUERY; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.LENIENT_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MAX_EXPANSIONS_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MINIMUM_SHOULD_MATCH_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.OPERATOR_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.PREFIX_LENGTH_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.SLOP_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TIE_BREAKER_FIELD; +import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TYPE_FIELD; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; @@ -112,27 +116,31 @@ public class Match extends FullTextFunction implements OptionalArgument, PostAna UNSIGNED_LONG, VERSION ); - - protected final Expression field; - - // Options for match function. They don’t need to be serialized as the data nodes will retrieve them from the query builder - private final transient Expression options; - - public static final Map ALLOWED_OPTIONS = Map.ofEntries( + public static final Map OPTIONS = Map.ofEntries( + entry(BOOST_FIELD.getPreferredName(), FLOAT), + entry(SLOP_FIELD.getPreferredName(), INTEGER), entry(ANALYZER_FIELD.getPreferredName(), KEYWORD), entry(GENERATE_SYNONYMS_PHRASE_QUERY.getPreferredName(), BOOLEAN), - entry(Fuzziness.FIELD.getPreferredName(), KEYWORD), - entry(BOOST_FIELD.getPreferredName(), FLOAT), - entry(FUZZY_TRANSPOSITIONS_FIELD.getPreferredName(), BOOLEAN), + entry(FUZZINESS_FIELD.getPreferredName(), KEYWORD), entry(FUZZY_REWRITE_FIELD.getPreferredName(), KEYWORD), + entry(FUZZY_TRANSPOSITIONS_FIELD.getPreferredName(), BOOLEAN), entry(LENIENT_FIELD.getPreferredName(), BOOLEAN), entry(MAX_EXPANSIONS_FIELD.getPreferredName(), INTEGER), entry(MINIMUM_SHOULD_MATCH_FIELD.getPreferredName(), KEYWORD), entry(OPERATOR_FIELD.getPreferredName(), KEYWORD), entry(PREFIX_LENGTH_FIELD.getPreferredName(), INTEGER), + entry(TIE_BREAKER_FIELD.getPreferredName(), FLOAT), + entry(TYPE_FIELD.getPreferredName(), KEYWORD), entry(ZERO_TERMS_QUERY_FIELD.getPreferredName(), KEYWORD) ); + private static final Set MULTIMATCH_SPECIFIC_OPTIONS = Set.of( + SLOP_FIELD.getPreferredName(), + TIE_BREAKER_FIELD.getPreferredName(), + TYPE_FIELD.getPreferredName() + ); + + // TODO: update descriptions and comments. @FunctionInfo( returnType = "boolean", appliesTo = { @@ -160,15 +168,15 @@ public class Match extends FullTextFunction implements OptionalArgument, PostAna public Match( Source source, @Param( - name = "field", - type = { "keyword", "text", "boolean", "date", "date_nanos", "double", "integer", "ip", "long", "unsigned_long", "version" }, - description = "Field that the query will target." - ) Expression field, + name = "fields", + type = { "keyword", "boolean", "date", "date_nanos", "double", "integer", "ip", "long", "text", "unsigned_long", "version" }, + description = "Fields to use for matching" + ) List fields, @Param( name = "query", type = { "keyword", "boolean", "date", "date_nanos", "double", "integer", "ip", "long", "unsigned_long", "version" }, - description = "Value to find in the provided field." - ) Expression matchQuery, + description = "Value to find in the provided fields." + ) Expression query, @MapParam( name = "options", description = "(Optional) Match additional options as <>.", @@ -224,7 +232,7 @@ public Match( type = "boolean", valueHint = { "true", "false" }, description = "If false, format-based errors, such as providing a text query value for a numeric field, are returned. " - + "Defaults to false." + + "Defaults to true." ), @MapParam.MapParamEntry( name = "max_expansions", @@ -250,6 +258,20 @@ public Match( valueHint = { "1" }, description = "Number of beginning characters left unchanged for fuzzy matching. Defaults to 0." ), + @MapParam.MapParamEntry( + name = "tie_breaker", + type = "float", + valueHint = { "0" }, + description = "Controls how score is blended together between field groups. Defaults to 0 (best score from each group)." + ), + @MapParam.MapParamEntry( + name = "type", + type = "object", + valueHint = { "'best_fields'" }, + description = "Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, " + + "`cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. " + + "See <>." + ), @MapParam.MapParamEntry( name = "zero_terms_query", type = "keyword", @@ -260,13 +282,33 @@ public Match( optional = true ) Expression options ) { - this(source, field, matchQuery, options, null); + this(source, fields, query, options, null); } - public Match(Source source, Expression field, Expression matchQuery, Expression options, QueryBuilder queryBuilder) { - super(source, matchQuery, options == null ? List.of(field, matchQuery) : List.of(field, matchQuery, options), queryBuilder); - this.field = field; - this.options = options; + // Due to current limitations, the options field may contain a field, in which case treat it as a field, and use "null" for actual + // options. We also remember the originally supplied arguments in order to make tests happy. + private final transient List fields; + private final transient List fieldsOriginal; + private final transient Expression options; + private final transient Expression optionsOriginal; + + private static List initChildren(Expression query, List fields, Expression options) { + Stream fieldsAndQuery = Stream.concat(Stream.of(query), fields.stream()); + return (options == null ? fieldsAndQuery : Stream.concat(fieldsAndQuery, Stream.of(options))).toList(); + } + + protected Match(Source source, List fields, Expression query, Expression options, QueryBuilder queryBuilder) { + super(source, query, initChildren(query, fields, options), queryBuilder); + this.fieldsOriginal = fields; + this.optionsOriginal = options; + + if (options == null || options instanceof MapExpression) { + this.fields = fields; + this.options = options; + } else { + this.fields = Stream.concat(fields.stream(), Stream.of(options)).toList(); + this.options = null; + } } @Override @@ -276,41 +318,41 @@ public String getWriteableName() { private static Match readFrom(StreamInput in) throws IOException { Source source = Source.readFrom((PlanStreamInput) in); - Expression field = in.readNamedWriteable(Expression.class); Expression query = in.readNamedWriteable(Expression.class); - QueryBuilder queryBuilder = null; - if (in.getTransportVersion().onOrAfter(TransportVersions.ESQL_QUERY_BUILDER_IN_SEARCH_FUNCTIONS)) { - queryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class); - } - return new Match(source, field, query, null, queryBuilder); + List fields = in.readNamedWriteableCollectionAsList(Expression.class); + QueryBuilder queryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class); + return new Match(source, fields, query, null, queryBuilder); } // This is not meant to be overriden by MatchOperator - MatchOperator should be serialized to Match @Override public final void writeTo(StreamOutput out) throws IOException { source().writeTo(out); - out.writeNamedWriteable(field()); out.writeNamedWriteable(query()); - if (out.getTransportVersion().onOrAfter(TransportVersions.ESQL_QUERY_BUILDER_IN_SEARCH_FUNCTIONS)) { - out.writeOptionalNamedWriteable(queryBuilder()); - } + out.writeNamedWriteableCollection(fields); + out.writeOptionalNamedWriteable(queryBuilder()); } @Override protected TypeResolution resolveParams() { - return resolveField().and(resolveQuery()).and(resolveOptions(options(), THIRD)).and(checkParamCompatibility()); + return resolveFields().and(resolveQuery()).and(resolveOptions(options(), THIRD)).and(checkParamCompatibility()); } - private TypeResolution resolveField() { - return isNotNull(field, sourceText(), FIRST).and( - isType( - field, - FIELD_DATA_TYPES::contains, - sourceText(), - FIRST, - "keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version" + private TypeResolution resolveFields() { + return fields.stream() + .map( + (Expression field) -> isNotNull(field, sourceText(), FIRST).and( + isType( + field, + FIELD_DATA_TYPES::contains, + sourceText(), + FIRST, + "keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version" + ) + ) ) - ); + .reduce(TypeResolution::and) + .orElse(null); } private TypeResolution resolveQuery() { @@ -324,22 +366,30 @@ private TypeResolution resolveQuery() { } private TypeResolution checkParamCompatibility() { - DataType fieldType = field().dataType(); DataType queryType = query().dataType(); - // Field and query types should match. If the query is a string, then it can match any field type. - if ((fieldType == queryType) || (queryType == KEYWORD)) { - return TypeResolution.TYPE_RESOLVED; - } + return fields.stream().map((Expression field) -> { + DataType fieldType = field.dataType(); - if (fieldType.isNumeric() && queryType.isNumeric()) { - // When doing an unsigned long query, field must be an unsigned long - if ((queryType == UNSIGNED_LONG && fieldType != UNSIGNED_LONG) == false) { + // Field and query types should match. If the query is a string, then it can match any field type. + if ((fieldType == queryType) || (queryType == KEYWORD)) { return TypeResolution.TYPE_RESOLVED; } - } - return new TypeResolution(formatIncompatibleTypesMessage(fieldType, queryType, sourceText())); + if (fieldType.isNumeric() && queryType.isNumeric()) { + // When doing an unsigned long query, field must be an unsigned long + if ((queryType == UNSIGNED_LONG && fieldType != UNSIGNED_LONG) == false) { + return TypeResolution.TYPE_RESOLVED; + } + } + + return new TypeResolution(formatIncompatibleTypesMessage(fieldType, queryType, sourceText())); + }).reduce(TypeResolution::and).orElse(null); + } + + @Override + public String functionName() { + return ENTRY.name; } @Override @@ -348,20 +398,17 @@ protected Map resolvedOptions() { } private Map matchQueryOptions() throws InvalidArgumentException { + Map options = new HashMap<>(); if (options() == null) { - return Map.of(LENIENT_FIELD.getPreferredName(), true); + return options; } - Map matchOptions = new HashMap<>(); - // Match is lenient by default to avoid failing on incompatible types - matchOptions.put(LENIENT_FIELD.getPreferredName(), true); - - populateOptionsMap((MapExpression) options(), matchOptions, SECOND, sourceText(), ALLOWED_OPTIONS); - return matchOptions; + Match.populateOptionsMap((MapExpression) options(), options, THIRD, sourceText(), OPTIONS); + return options; } - public Expression field() { - return field; + public List fields() { + return fields; } public Expression options() { @@ -370,40 +417,50 @@ public Expression options() { @Override protected NodeInfo info() { - return NodeInfo.create(this, Match::new, field(), query(), options(), queryBuilder()); + // Specifically create new instance with original arguments. + return NodeInfo.create(this, Match::new, fieldsOriginal, query(), optionsOriginal); } @Override public Expression replaceChildren(List newChildren) { - return new Match( - source(), - newChildren.get(0), - newChildren.get(1), - newChildren.size() > 2 ? newChildren.get(2) : null, - queryBuilder() - ); + // "query" is the first child. + if (newChildren.getLast() instanceof MapExpression || newChildren.size() == children().size()) { + // if the last child is a MapExpression, it is the options map + return new Match( + source(), + newChildren.subList(1, newChildren.size() - 1), + newChildren.getFirst(), + newChildren.getLast(), + queryBuilder() + ); + } + + return new Match(source(), newChildren.subList(1, newChildren.size()), newChildren.getFirst(), null, queryBuilder()); } @Override public Expression replaceQueryBuilder(QueryBuilder queryBuilder) { - return new Match(source(), field, query(), options(), queryBuilder); + // Specifically create new instance with original arguments. + return new Match(source(), fieldsOriginal, query(), optionsOriginal, queryBuilder); } @Override public BiConsumer postAnalysisPlanVerification() { return (plan, failures) -> { super.postAnalysisPlanVerification().accept(plan, failures); - plan.forEachExpression(Match.class, m -> { - if (m.fieldAsFieldAttribute() == null) { - failures.add( - Failure.fail( - m.field(), - "[{}] {} cannot operate on [{}], which is not a field from an index mapping", - functionName(), - functionType(), - m.field().sourceText() - ) - ); + plan.forEachExpression(Match.class, match -> { + for (Expression field : fields) { + if (fieldAsFieldAttribute(field) == null) { + failures.add( + Failure.fail( + field, + "[{}] {} cannot operate on [{}], which is not a field from an index mapping", + functionName(), + functionType(), + field.sourceText() + ) + ); + } } }); }; @@ -437,15 +494,23 @@ public Object queryAsObject() { @Override protected Query translate(TranslatorHandler handler) { - var fieldAttribute = fieldAsFieldAttribute(); - Check.notNull(fieldAttribute, "Match must have a field attribute as the first argument"); - String fieldName = getNameFromFieldAttribute(fieldAttribute); - // Make query lenient so mixed field types can be queried when a field type is incompatible with the value provided - return new MatchQuery(source(), fieldName, queryAsObject(), matchQueryOptions()); - } + Map fieldsWithBoost = new HashMap<>(); + for (Expression field : fields) { + var fieldAttribute = fieldAsFieldAttribute(field); + Check.notNull(fieldAttribute, "Match must have field attributes as arguments #1 to #N-1."); + String fieldName = getNameFromFieldAttribute(fieldAttribute); + fieldsWithBoost.put(fieldName, 1.0f); + } - private FieldAttribute fieldAsFieldAttribute() { - return fieldAsFieldAttribute(field); + var options = matchQueryOptions(); + if (fieldsWithBoost.size() != 1 || options.keySet().stream().anyMatch(MULTIMATCH_SPECIFIC_OPTIONS::contains)) { + // For 0 or 2+ fields, or with multimatch-specific options, translate to multi_match. + return new MultiMatchQuery(source(), Objects.toString(queryAsObject()), fieldsWithBoost, options); + } else { + // Translate to Match when having exactly one field. + options.put(MatchQueryBuilder.LENIENT_FIELD.getPreferredName(), true); + return new MatchQuery(source(), fieldsWithBoost.keySet().stream().findFirst().get(), queryAsObject(), options); + } } @Override @@ -454,13 +519,13 @@ public boolean equals(Object o) { // ignore options when comparing two Match functions if (o == null || getClass() != o.getClass()) return false; Match match = (Match) o; - return Objects.equals(field(), match.field()) + return Objects.equals(fields(), match.fields()) && Objects.equals(query(), match.query()) && Objects.equals(queryBuilder(), match.queryBuilder()); } @Override public int hashCode() { - return Objects.hash(field(), query(), queryBuilder()); + return Objects.hash(fields(), query(), queryBuilder()); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchOperator.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchOperator.java index 64dcc1dcd150e..2c725f081b69e 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchOperator.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchOperator.java @@ -58,11 +58,11 @@ public MatchOperator( description = "Value to find in the provided field." ) Expression matchQuery ) { - super(source, field, matchQuery, null, null); + super(source, List.of(field), matchQuery, null, null); } private MatchOperator(Source source, Expression field, Expression matchQuery, QueryBuilder queryBuilder) { - super(source, field, matchQuery, null, queryBuilder); + super(source, List.of(field), matchQuery, null, queryBuilder); } @Override @@ -77,16 +77,17 @@ public String functionName() { @Override protected NodeInfo info() { - return NodeInfo.create(this, MatchOperator::new, field(), query()); + return NodeInfo.create(this, MatchOperator::new, fields().getFirst(), query()); } @Override public Expression replaceChildren(List newChildren) { - return new MatchOperator(source(), newChildren.get(0), newChildren.get(1), queryBuilder()); + // Query first, then field. + return new MatchOperator(source(), newChildren.get(1), newChildren.get(0), queryBuilder()); } @Override public Expression replaceQueryBuilder(QueryBuilder queryBuilder) { - return new MatchOperator(source(), field, query(), queryBuilder); + return new MatchOperator(source(), fields().getFirst(), query(), queryBuilder); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatch.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatch.java deleted file mode 100644 index 2c398c7f6c6f1..0000000000000 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatch.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.fulltext; - -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.index.query.MatchQueryBuilder; -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.xpack.esql.capabilities.PostAnalysisPlanVerificationAware; -import org.elasticsearch.xpack.esql.common.Failure; -import org.elasticsearch.xpack.esql.common.Failures; -import org.elasticsearch.xpack.esql.core.InvalidArgumentException; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.expression.MapExpression; -import org.elasticsearch.xpack.esql.core.querydsl.query.Query; -import org.elasticsearch.xpack.esql.core.tree.NodeInfo; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.core.util.Check; -import org.elasticsearch.xpack.esql.expression.function.Example; -import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo; -import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle; -import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; -import org.elasticsearch.xpack.esql.expression.function.MapParam; -import org.elasticsearch.xpack.esql.expression.function.OptionalArgument; -import org.elasticsearch.xpack.esql.expression.function.Param; -import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; -import org.elasticsearch.xpack.esql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.esql.planner.TranslatorHandler; -import org.elasticsearch.xpack.esql.querydsl.query.MultiMatchQuery; - -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - -import static java.util.Map.entry; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.ANALYZER_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.BOOST_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZINESS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_REWRITE_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_TRANSPOSITIONS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.GENERATE_SYNONYMS_PHRASE_QUERY; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.LENIENT_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MAX_EXPANSIONS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MINIMUM_SHOULD_MATCH_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.OPERATOR_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.PREFIX_LENGTH_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.SLOP_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TIE_BREAKER_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TYPE_FIELD; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.FIRST; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.SECOND; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.THIRD; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isMapExpression; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNotNull; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isNotNullAndFoldable; -import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType; -import static org.elasticsearch.xpack.esql.core.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.esql.core.type.DataType.DATETIME; -import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_NANOS; -import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; -import static org.elasticsearch.xpack.esql.core.type.DataType.FLOAT; -import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; -import static org.elasticsearch.xpack.esql.core.type.DataType.IP; -import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; -import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; -import static org.elasticsearch.xpack.esql.core.type.DataType.UNSIGNED_LONG; -import static org.elasticsearch.xpack.esql.core.type.DataType.VERSION; - -/** - * Full text function that performs a {@link org.elasticsearch.xpack.esql.querydsl.query.MultiMatchQuery} . - */ -public class MultiMatch extends FullTextFunction implements OptionalArgument, PostAnalysisPlanVerificationAware { - public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry( - Expression.class, - "MultiMatch", - MultiMatch::readFrom - ); - - public static final Set QUERY_DATA_TYPES = Set.of( - KEYWORD, - BOOLEAN, - DATETIME, - DATE_NANOS, - DOUBLE, - INTEGER, - IP, - LONG, - UNSIGNED_LONG, - VERSION - ); - - public static final Set FIELD_DATA_TYPES = Set.of( - KEYWORD, - TEXT, - BOOLEAN, - DATETIME, - DATE_NANOS, - DOUBLE, - INTEGER, - IP, - LONG, - UNSIGNED_LONG, - VERSION - ); - - public static final Map OPTIONS = Map.ofEntries( - entry(BOOST_FIELD.getPreferredName(), FLOAT), - entry(SLOP_FIELD.getPreferredName(), INTEGER), - // TODO: add "zero_terms_query" - entry(ANALYZER_FIELD.getPreferredName(), KEYWORD), - entry(GENERATE_SYNONYMS_PHRASE_QUERY.getPreferredName(), BOOLEAN), - entry(FUZZINESS_FIELD.getPreferredName(), KEYWORD), - entry(FUZZY_REWRITE_FIELD.getPreferredName(), KEYWORD), - entry(FUZZY_TRANSPOSITIONS_FIELD.getPreferredName(), BOOLEAN), - entry(LENIENT_FIELD.getPreferredName(), BOOLEAN), - entry(MAX_EXPANSIONS_FIELD.getPreferredName(), INTEGER), - entry(MINIMUM_SHOULD_MATCH_FIELD.getPreferredName(), KEYWORD), - entry(OPERATOR_FIELD.getPreferredName(), KEYWORD), - entry(PREFIX_LENGTH_FIELD.getPreferredName(), INTEGER), - entry(TIE_BREAKER_FIELD.getPreferredName(), FLOAT), - entry(TYPE_FIELD.getPreferredName(), KEYWORD) - ); - - @FunctionInfo( - returnType = "boolean", - preview = true, - description = """ - Use `MULTI_MATCH` to perform a <> on the specified field. - The multi_match query builds on the match query to allow multi-field queries.""", - examples = { - @Example(file = "multi-match-function", tag = "multi-match-with-field"), - @Example(file = "multi-match-function", tag = "multi-match-with-named-function-params") }, - appliesTo = { - @FunctionAppliesTo( - lifeCycle = FunctionAppliesToLifecycle.COMING, - version = "9.1.0", - description = "Support for optional named parameters is only available from 9.1.0" - ) } - ) - public MultiMatch( - Source source, - @Param( - name = "query", - type = { "keyword", "boolean", "date", "date_nanos", "double", "integer", "ip", "long", "text", "unsigned_long", "version" }, - description = "Value to find in the provided fields." - ) Expression query, - @Param( - name = "fields", - type = { "keyword", "boolean", "date", "date_nanos", "double", "integer", "ip", "long", "unsigned_long", "version" }, - description = "Fields to use for matching" - ) List fields, - @MapParam( - name = "options", - params = { - @MapParam.MapParamEntry( - name = "boost", - type = "float", - valueHint = { "2.5" }, - description = "Floating point number used to decrease or increase the relevance scores of the query." - ), - @MapParam.MapParamEntry( - name = "analyzer", - type = "keyword", - valueHint = { "standard" }, - description = "Analyzer used to convert the text in the query value into token. Defaults to the index-time analyzer" - + " mapped for the field. If no analyzer is mapped, the index’s default analyzer is used." - ), - @MapParam.MapParamEntry( - name = "auto_generate_synonyms_phrase_query", - type = "boolean", - valueHint = { "true", "false" }, - description = "If true, match phrase queries are automatically created for multi-term synonyms. Defaults to true." - ), - @MapParam.MapParamEntry( - name = "fuzziness", - type = "keyword", - valueHint = { "AUTO", "1", "2" }, - description = "Maximum edit distance allowed for matching." - ), - @MapParam.MapParamEntry( - name = "fuzzy_rewrite", - type = "keyword", - valueHint = { - "constant_score_blended", - "constant_score", - "constant_score_boolean", - "top_terms_blended_freqs_N", - "top_terms_boost_N", - "top_terms_N" }, - description = "Method used to rewrite the query. See the rewrite parameter for valid values and more information. " - + "If the fuzziness parameter is not 0, the match query uses a fuzzy_rewrite method of " - + "top_terms_blended_freqs_${max_expansions} by default." - ), - @MapParam.MapParamEntry( - name = "fuzzy_transpositions", - type = "boolean", - valueHint = { "true", "false" }, - description = "If true, edits for fuzzy matching include transpositions of two adjacent characters (ab → ba). " - + "Defaults to true." - ), - @MapParam.MapParamEntry( - name = "lenient", - type = "boolean", - valueHint = { "true", "false" }, - description = "If false, format-based errors, such as providing a text query value for a numeric field, are returned. " - + "Defaults to true." - ), - @MapParam.MapParamEntry( - name = "max_expansions", - type = "integer", - valueHint = { "50" }, - description = "Maximum number of terms to which the query will expand. Defaults to 50." - ), - @MapParam.MapParamEntry( - name = "minimum_should_match", - type = "integer", - valueHint = { "2" }, - description = "Minimum number of clauses that must match for a document to be returned." - ), - @MapParam.MapParamEntry( - name = "operator", - type = "keyword", - valueHint = { "AND", "OR" }, - description = "Boolean logic used to interpret text in the query value. Defaults to OR." - ), - @MapParam.MapParamEntry( - name = "prefix_length", - type = "integer", - valueHint = { "1" }, - description = "Number of beginning characters left unchanged for fuzzy matching. Defaults to 0." - ), - @MapParam.MapParamEntry( - name = "tie_breaker", - type = "float", - valueHint = { "0" }, - description = "Controls how score is blended together between field groups. Defaults to 0 (best score from each group)." - ), - @MapParam.MapParamEntry( - name = "type", - type = "object", - valueHint = { "'best_fields'" }, - description = "Controls the way multi_match is executed internally. Can be one of `best_fields`, `most_fields`, " - + "`cross_fields`, `phrase`, `phrase_prefix` or `bool_prefix`. Defaults to 'best_fields'. " - + "See <>." - ), }, - description = "(Optional) Additional options for MultiMatch, " - + "passed as <>.\"\n" - + " See <> for more information.", - optional = true - ) Expression options - ) { - this(source, query, fields, options, null); - } - - // Due to current limitations, the options field may contain a field, in which case treat it as a field, and use "null" for actual - // options. We also remember the originally supplied arguments in order to make tests happy. - private final transient List fields; - private final transient List fieldsOriginal; - private final transient Expression options; - private final transient Expression optionsOriginal; - - private static List initChildren(Expression query, List fields, Expression options) { - Stream fieldsAndQuery = Stream.concat(Stream.of(query), fields.stream()); - return (options == null ? fieldsAndQuery : Stream.concat(fieldsAndQuery, Stream.of(options))).toList(); - } - - private MultiMatch(Source source, Expression query, List fields, Expression options, QueryBuilder queryBuilder) { - super(source, query, initChildren(query, fields, options), queryBuilder); - this.fieldsOriginal = fields; - this.optionsOriginal = options; - - if (options == null || options instanceof MapExpression) { - this.fields = fields; - this.options = options; - } else { - this.fields = Stream.concat(fields.stream(), Stream.of(options)).toList(); - this.options = null; - } - } - - private static MultiMatch readFrom(StreamInput in) throws IOException { - Source source = Source.readFrom((PlanStreamInput) in); - Expression query = in.readNamedWriteable(Expression.class); - List fields = in.readNamedWriteableCollectionAsList(Expression.class); - QueryBuilder queryBuilder = in.readOptionalNamedWriteable(QueryBuilder.class); - return new MultiMatch(source, query, fields, null, queryBuilder); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - source().writeTo(out); - out.writeNamedWriteable(query()); - out.writeNamedWriteableCollection(fields); - out.writeOptionalNamedWriteable(queryBuilder()); - } - - @Override - public String getWriteableName() { - return ENTRY.name; - } - - @Override - public Expression replaceChildren(List newChildren) { - if (newChildren.getLast() instanceof MapExpression || newChildren.size() == children().size()) { - // if the last child is a MapExpression, it is the options map - return new MultiMatch( - source(), - newChildren.getFirst(), - newChildren.subList(1, newChildren.size() - 1), - newChildren.getLast(), - queryBuilder() - ); - } - - return new MultiMatch(source(), newChildren.getFirst(), newChildren.subList(1, newChildren.size()), null, queryBuilder()); - } - - @Override - protected NodeInfo info() { - // Specifically create new instance with original arguments. - return NodeInfo.create(this, MultiMatch::new, query(), fieldsOriginal, optionsOriginal); - } - - @Override - protected Query translate(TranslatorHandler handler) { - Map fieldsWithBoost = new HashMap<>(); - for (Expression field : fields) { - var fieldAttribute = Match.fieldAsFieldAttribute(field); - Check.notNull(fieldAttribute, "MultiMatch must have field attributes as arguments #2 to #N-1."); - String fieldName = Match.getNameFromFieldAttribute(fieldAttribute); - fieldsWithBoost.put(fieldName, 1.0f); - } - return new MultiMatchQuery(source(), Objects.toString(queryAsObject()), fieldsWithBoost, getOptions()); - } - - @Override - public Expression replaceQueryBuilder(QueryBuilder queryBuilder) { - // Specifically create new instance with original arguments. - return new MultiMatch(source(), query(), fieldsOriginal, optionsOriginal, queryBuilder); - } - - public List fields() { - return fields; - } - - public Expression options() { - return options; - } - - private Map getOptions() throws InvalidArgumentException { - Map options = new HashMap<>(); - options.put(MatchQueryBuilder.LENIENT_FIELD.getPreferredName(), true); - if (options() == null) { - return options; - } - - Match.populateOptionsMap((MapExpression) options(), options, THIRD, sourceText(), OPTIONS); - return options; - } - - @Override - public String functionName() { - return ENTRY.name; - } - - private TypeResolution resolveFields() { - return fields.stream() - .map( - (Expression field) -> isNotNull(field, sourceText(), SECOND).and( - isType( - field, - FIELD_DATA_TYPES::contains, - sourceText(), - SECOND, - "keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version" - ) - ) - ) - .reduce(TypeResolution::and) - .orElse(null); - } - - private TypeResolution resolveOptions() { - if (options() != null) { - TypeResolution resolution = isNotNull(options(), sourceText(), THIRD); - if (resolution.unresolved()) { - return resolution; - } - // MapExpression does not have a DataType associated with it - resolution = isMapExpression(options(), sourceText(), THIRD); - if (resolution.unresolved()) { - return resolution; - } - - try { - getOptions(); - } catch (InvalidArgumentException e) { - return new TypeResolution(e.getMessage()); - } - } - return TypeResolution.TYPE_RESOLVED; - } - - private TypeResolution resolveQuery() { - return isType( - query(), - QUERY_DATA_TYPES::contains, - sourceText(), - FIRST, - "keyword, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version" - ).and(isNotNullAndFoldable(query(), sourceText(), FIRST)); - } - - @Override - protected TypeResolution resolveParams() { - return resolveQuery().and(resolveFields()).and(resolveOptions()); - } - - @Override - public boolean equals(Object o) { - // MultiMatch does not serialize options, as they get included in the query builder. We need to override equals and hashcode to - // ignore options when comparing two MultiMatch functions - if (o == null || getClass() != o.getClass()) return false; - MultiMatch mm = (MultiMatch) o; - return Objects.equals(fields(), mm.fields()) - && Objects.equals(query(), mm.query()) - && Objects.equals(queryBuilder(), mm.queryBuilder()); - } - - @Override - public int hashCode() { - return Objects.hash(fields(), query(), queryBuilder()); - } - - @Override - public BiConsumer postAnalysisPlanVerification() { - return (plan, failures) -> { - super.postAnalysisPlanVerification().accept(plan, failures); - plan.forEachExpression(MultiMatch.class, mm -> { - for (Expression field : fields) { - if (Match.fieldAsFieldAttribute(field) == null) { - failures.add( - Failure.fail( - field, - "[{}] {} cannot operate on [{}], which is not a field from an index mapping", - functionName(), - functionType(), - field.sourceText() - ) - ); - } - } - }); - }; - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java index 5526283dfe5a0..5c4abfe80ddd2 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQuery.java @@ -6,11 +6,11 @@ */ package org.elasticsearch.xpack.esql.querydsl.query; -import org.elasticsearch.common.unit.Fuzziness; -import org.elasticsearch.index.query.MultiMatchQueryBuilder; +import org.elasticsearch.index.query.MultiFieldMatchQueryBuilder; import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.ZeroTermsQueryOption; import org.elasticsearch.xpack.esql.core.querydsl.query.Query; import org.elasticsearch.xpack.esql.core.tree.Source; @@ -20,43 +20,26 @@ import java.util.function.BiConsumer; import static java.util.Map.entry; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.ANALYZER_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.BOOST_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZINESS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_REWRITE_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.FUZZY_TRANSPOSITIONS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.GENERATE_SYNONYMS_PHRASE_QUERY; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.LENIENT_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MAX_EXPANSIONS_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.MINIMUM_SHOULD_MATCH_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.OPERATOR_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.PREFIX_LENGTH_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.SLOP_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TIE_BREAKER_FIELD; -import static org.elasticsearch.index.query.MultiMatchQueryBuilder.TYPE_FIELD; +import static org.elasticsearch.index.query.MultiFieldMatchQueryBuilder.BOOST_FIELD; +import static org.elasticsearch.index.query.MultiFieldMatchQueryBuilder.GENERATE_SYNONYMS_PHRASE_QUERY; +import static org.elasticsearch.index.query.MultiFieldMatchQueryBuilder.MINIMUM_SHOULD_MATCH_FIELD; +import static org.elasticsearch.index.query.MultiFieldMatchQueryBuilder.OPERATOR_FIELD; +import static org.elasticsearch.index.query.MultiFieldMatchQueryBuilder.ZERO_TERMS_QUERY_FIELD; public class MultiMatchQuery extends Query { - private static final Map> BUILDER_APPLIERS; + private static final Map> BUILDER_APPLIERS; static { BUILDER_APPLIERS = Map.ofEntries( entry(BOOST_FIELD.getPreferredName(), (qb, obj) -> qb.boost((Float) obj)), - entry(SLOP_FIELD.getPreferredName(), (qb, obj) -> qb.slop((Integer) obj)), - // TODO: add zero terms query support, I'm not sure the best way to parse it yet... - // appliers.put("zero_terms_query", (qb, s) -> qb.zeroTermsQuery(s)); - entry(ANALYZER_FIELD.getPreferredName(), (qb, obj) -> qb.analyzer((String) obj)), + entry( + ZERO_TERMS_QUERY_FIELD.getPreferredName(), + (qb, obj) -> qb.zeroTermsQuery(ZeroTermsQueryOption.readFromString((String) obj)) + ), entry(GENERATE_SYNONYMS_PHRASE_QUERY.getPreferredName(), (qb, obj) -> qb.autoGenerateSynonymsPhraseQuery((Boolean) obj)), - entry(FUZZINESS_FIELD.getPreferredName(), (qb, obj) -> qb.fuzziness(Fuzziness.fromString((String) obj))), - entry(FUZZY_REWRITE_FIELD.getPreferredName(), (qb, obj) -> qb.fuzzyRewrite((String) obj)), - entry(FUZZY_TRANSPOSITIONS_FIELD.getPreferredName(), (qb, obj) -> qb.fuzzyTranspositions((Boolean) obj)), - entry(LENIENT_FIELD.getPreferredName(), (qb, obj) -> qb.lenient((Boolean) obj)), - entry(MAX_EXPANSIONS_FIELD.getPreferredName(), (qb, obj) -> qb.maxExpansions((Integer) obj)), entry(MINIMUM_SHOULD_MATCH_FIELD.getPreferredName(), (qb, obj) -> qb.minimumShouldMatch((String) obj)), - entry(OPERATOR_FIELD.getPreferredName(), (qb, obj) -> qb.operator(Operator.fromString((String) obj))), - entry(PREFIX_LENGTH_FIELD.getPreferredName(), (qb, obj) -> qb.prefixLength((Integer) obj)), - entry(TIE_BREAKER_FIELD.getPreferredName(), (qb, obj) -> qb.tieBreaker((Float) obj)), - entry(TYPE_FIELD.getPreferredName(), (qb, obj) -> qb.type((String) obj)) + entry(OPERATOR_FIELD.getPreferredName(), (qb, obj) -> qb.operator(Operator.fromString((String) obj))) ); } @@ -73,7 +56,7 @@ public MultiMatchQuery(Source source, String query, Map fields, M @Override protected QueryBuilder asBuilder() { - final MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(query); + final MultiFieldMatchQueryBuilder queryBuilder = QueryBuilders.multiFieldMatchQuery(query); queryBuilder.fields(fields); options.forEach((k, v) -> { if (BUILDER_APPLIERS.containsKey(k)) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 6935a1efac2ae..3f29c4bebc42d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -326,7 +326,7 @@ public final void test() throws Throwable { ); assumeFalse( "CSV tests cannot currently handle multi_match function that depends on Lucene", - testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.capabilityName()) + testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.MULTI_MATCH_UNIFIED_FUNCTION.capabilityName()) ); if (Build.current().isSnapshot()) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index b99050b8ef090..4f9d50219d3cc 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -47,7 +47,6 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.Min; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchOperator; -import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDateNanos; @@ -2896,11 +2895,11 @@ public void testFunctionNamedParamsAsFunctionArgument1() { public void testFunctionNamedParamsAsFunctionArgument2() { LogicalPlan plan = analyze(""" from test - | WHERE MULTI_MATCH("Anna Smith", first_name, last_name, {"minimum_should_match": 3.0}) + | WHERE MATCH(first_name, last_name, "Anna Smith", {"minimum_should_match": 3.0}) """); Limit limit = as(plan, Limit.class); Filter filter = as(limit.child(), Filter.class); - MultiMatch mm = as(filter.condition(), MultiMatch.class); + Match mm = as(filter.condition(), Match.class); MapExpression me = as(mm.options(), MapExpression.class); assertEquals(1, me.entryExpressions().size()); EntryExpression ee = as(me.entryExpressions().get(0), EntryExpression.class); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 14e5c0615e2b4..8ac0ee1d9e674 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -20,7 +20,6 @@ import org.elasticsearch.xpack.esql.core.type.UnsupportedEsField; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.MatchPhrase; -import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.vector.Knn; import org.elasticsearch.xpack.esql.index.EsIndex; @@ -1218,8 +1217,8 @@ public void testMatchInsideEval() throws Exception { } public void testFieldBasedFullTextFunctions() throws Exception { - checkFieldBasedWithNonIndexedColumn("MATCH", "match(text, \"cat\")", "function"); - checkFieldBasedFunctionNotAllowedAfterCommands("MATCH", "function", "match(title, \"Meditation\")"); + checkFieldBasedWithNonIndexedColumn("Match", "match(text, \"cat\")", "function"); + checkFieldBasedFunctionNotAllowedAfterCommands("Match", "function", "match(title, \"Meditation\")"); checkFieldBasedWithNonIndexedColumn(":", "text : \"cat\"", "operator"); checkFieldBasedFunctionNotAllowedAfterCommands(":", "operator", "title : \"Meditation\""); @@ -1227,10 +1226,6 @@ public void testFieldBasedFullTextFunctions() throws Exception { checkFieldBasedWithNonIndexedColumn("MatchPhrase", "match_phrase(text, \"cat\")", "function"); checkFieldBasedFunctionNotAllowedAfterCommands("MatchPhrase", "function", "match_phrase(title, \"Meditation\")"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFieldBasedWithNonIndexedColumn("MultiMatch", "multi_match(\"cat\", text)", "function"); - checkFieldBasedFunctionNotAllowedAfterCommands("MultiMatch", "function", "multi_match(\"Meditation\", title)"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFieldBasedWithNonIndexedColumn("Term", "term(text, \"cat\")", "function"); checkFieldBasedFunctionNotAllowedAfterCommands("Term", "function", "term(title, \"Meditation\")"); @@ -1357,7 +1352,7 @@ private void checkNonFieldBasedFullTextFunctionsNotAllowedAfterCommands(String f } public void testFullTextFunctionsOnlyAllowedInWhere() throws Exception { - checkFullTextFunctionsOnlyAllowedInWhere("MATCH", "match(title, \"Meditation\")", "function"); + checkFullTextFunctionsOnlyAllowedInWhere("Match", "match(title, \"Meditation\")", "function"); checkFullTextFunctionsOnlyAllowedInWhere(":", "title:\"Meditation\"", "operator"); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Meditation\")", "function"); checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Meditation\")", "function"); @@ -1365,14 +1360,24 @@ public void testFullTextFunctionsOnlyAllowedInWhere() throws Exception { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFullTextFunctionsOnlyAllowedInWhere("Term", "term(title, \"Meditation\")", "function"); } - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFullTextFunctionsOnlyAllowedInWhere("MultiMatch", "multi_match(\"Meditation\", title, body)", "function"); - } if (EsqlCapabilities.Cap.KNN_FUNCTION.isEnabled()) { checkFullTextFunctionsOnlyAllowedInWhere("KNN", "knn(vector, [0, 1, 2])", "function"); } } + public void testMatchFunctionOnlyAllowedInWhere() throws Exception { + checkFullTextFunctionsOnlyAllowedInWhere("Match", "match(title, \"Anna\")", "function"); + } + + public void testTermFunctionOnlyAllowedInWhere() throws Exception { + assumeTrue("term function capability not available", EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()); + checkFullTextFunctionsOnlyAllowedInWhere("Term", "term(title, \"Anna\")", "function"); + } + + public void testMatchOperatornOnlyAllowedInWhere() throws Exception { + checkFullTextFunctionsOnlyAllowedInWhere(":", "title:\"Anna\"", "operator"); + } + private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, String functionInvocation, String functionType) throws Exception { assertThat( @@ -1401,9 +1406,6 @@ public void testFullTextFunctionsDisjunctions() { checkWithFullTextFunctionsDisjunctions("qstr(\"title: Meditation\")"); checkWithFullTextFunctionsDisjunctions("kql(\"title: Meditation\")"); checkWithFullTextFunctionsDisjunctions("match_phrase(title, \"Meditation\")"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkWithFullTextFunctionsDisjunctions("multi_match(\"Meditation\", title, body)"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkWithFullTextFunctionsDisjunctions("term(title, \"Meditation\")"); } @@ -1461,14 +1463,11 @@ private void checkWithFullTextFunctionsDisjunctions(String functionInvocation) { } public void testFullTextFunctionsWithNonBooleanFunctions() { - checkFullTextFunctionsWithNonBooleanFunctions("MATCH", "match(title, \"Meditation\")", "function"); + checkFullTextFunctionsWithNonBooleanFunctions("Match", "match(title, \"Meditation\")", "function"); checkFullTextFunctionsWithNonBooleanFunctions(":", "title:\"Meditation\"", "operator"); checkFullTextFunctionsWithNonBooleanFunctions("QSTR", "qstr(\"title: Meditation\")", "function"); checkFullTextFunctionsWithNonBooleanFunctions("KQL", "kql(\"title: Meditation\")", "function"); checkFullTextFunctionsWithNonBooleanFunctions("MatchPhrase", "match_phrase(title, \"Meditation\")", "function"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFullTextFunctionsWithNonBooleanFunctions("MultiMatch", "multi_match(\"Meditation\", title, body)", "function"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFullTextFunctionsWithNonBooleanFunctions("Term", "term(title, \"Meditation\")", "function"); } @@ -1537,9 +1536,6 @@ public void testFullTextFunctionsTargetsExistingField() throws Exception { testFullTextFunctionTargetsExistingField("match(title, \"Meditation\")"); testFullTextFunctionTargetsExistingField("title : \"Meditation\""); testFullTextFunctionTargetsExistingField("match_phrase(title, \"Meditation\")"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - testFullTextFunctionTargetsExistingField("multi_match(\"Meditation\", title)"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { testFullTextFunctionTargetsExistingField("term(fist_name, \"Meditation\")"); } @@ -2065,12 +2061,9 @@ public void testLookupJoinDataTypeMismatch() { } public void testFullTextFunctionOptions() { - checkOptionDataTypes(Match.ALLOWED_OPTIONS, "FROM test | WHERE match(title, \"Jean\", {\"%s\": %s})"); + checkOptionDataTypes(Match.OPTIONS, "FROM test | WHERE match(title, \"Jean\", {\"%s\": %s})"); checkOptionDataTypes(QueryString.ALLOWED_OPTIONS, "FROM test | WHERE QSTR(\"title: Jean\", {\"%s\": %s})"); checkOptionDataTypes(MatchPhrase.ALLOWED_OPTIONS, "FROM test | WHERE MATCH_PHRASE(title, \"Jean\", {\"%s\": %s})"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkOptionDataTypes(MultiMatch.OPTIONS, "FROM test | WHERE MULTI_MATCH(\"Jean\", title, body, {\"%s\": %s})"); - } if (EsqlCapabilities.Cap.KNN_FUNCTION.isEnabled()) { checkOptionDataTypes(Knn.ALLOWED_OPTIONS, "FROM test | WHERE KNN(vector, [0.1, 0.2, 0.3], {\"%s\": %s})"); } @@ -2129,9 +2122,6 @@ public void testFullTextFunctionCurrentlyUnsupportedBehaviour() throws Exception testFullTextFunctionsCurrentlyUnsupportedBehaviour("match(title, \"Meditation\")"); testFullTextFunctionsCurrentlyUnsupportedBehaviour("title : \"Meditation\""); testFullTextFunctionsCurrentlyUnsupportedBehaviour("match_phrase(title, \"Meditation\")"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - testFullTextFunctionsCurrentlyUnsupportedBehaviour("multi_match(\"Meditation\", title)"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { testFullTextFunctionsCurrentlyUnsupportedBehaviour("term(title, \"Meditation\")"); } @@ -2151,10 +2141,6 @@ public void testFullTextFunctionsNullArgs() throws Exception { checkFullTextFunctionNullArgs("kql(null)", ""); checkFullTextFunctionNullArgs("match_phrase(null, \"query\")", "first"); checkFullTextFunctionNullArgs("match_phrase(title, null)", "second"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFullTextFunctionNullArgs("multi_match(null, title)", "first"); - checkFullTextFunctionNullArgs("multi_match(\"query\", null)", "second"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFullTextFunctionNullArgs("term(null, \"query\")", "first"); checkFullTextFunctionNullArgs("term(title, null)", "second"); @@ -2177,10 +2163,6 @@ public void testFullTextFunctionsConstantQuery() throws Exception { checkFullTextFunctionsConstantQuery("qstr(title)", ""); checkFullTextFunctionsConstantQuery("kql(title)", ""); checkFullTextFunctionsConstantQuery("match_phrase(title, tags)", "second"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFullTextFunctionsConstantQuery("multi_match(category, body)", "first"); - checkFullTextFunctionsConstantQuery("multi_match(concat(title, \"world\"), title)", "first"); - } if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFullTextFunctionsConstantQuery("term(title, tags)", "second"); } @@ -2211,9 +2193,6 @@ public void testFullTextFunctionsInStats() { checkFullTextFunctionsInStats("qstr(\"title: Meditation\")"); checkFullTextFunctionsInStats("kql(\"title: Meditation\")"); checkFullTextFunctionsInStats("match_phrase(title, \"Meditation\")"); - if (EsqlCapabilities.Cap.MULTI_MATCH_FUNCTION.isEnabled()) { - checkFullTextFunctionsInStats("multi_match(\"Meditation\", title, body)"); - } if (EsqlCapabilities.Cap.KNN_FUNCTION.isEnabled()) { checkFullTextFunctionsInStats("knn(vector, [0, 1, 2])"); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchErrorTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchErrorTests.java deleted file mode 100644 index a60a522b86aa4..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchErrorTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -package org.elasticsearch.xpack.esql.expression.function.fulltext; - -import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.xpack.esql.core.expression.Expression; -import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; -import org.elasticsearch.xpack.esql.core.expression.TypeResolutions; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase; -import org.elasticsearch.xpack.esql.expression.function.ErrorsForCasesWithoutExamplesTestCase; -import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; -import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison; -import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates; -import org.hamcrest.Matcher; - -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.esql.planner.TranslatorHandler.TRANSLATOR_HANDLER; -import static org.hamcrest.Matchers.equalTo; - -public class MatchErrorTests extends ErrorsForCasesWithoutExamplesTestCase { - - @Override - protected List cases() { - return paramsToSuppliers(MatchTests.parameters()); - } - - @Override - protected Expression build(Source source, List args) { - Match match = new Match(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); - // We need to add the QueryBuilder to the match expression, as it is used to implement equals() and hashCode() and - // thus test the serialization methods. But we can only do this if the parameters make sense . - if (args.get(0) instanceof FieldAttribute && args.get(1).foldable()) { - QueryBuilder queryBuilder = TRANSLATOR_HANDLER.asQuery(LucenePushdownPredicates.DEFAULT, match).toQueryBuilder(); - match.replaceQueryBuilder(queryBuilder); - } - return match; - } - - @Override - protected Matcher expectedTypeErrorMatcher(List> validPerPosition, List signature) { - return equalTo( - errorMessageStringForMatch(validPerPosition, signature, (l, p) -> p == 0 ? FIELD_TYPE_ERROR_STRING : QUERY_TYPE_ERROR_STRING) - ); - } - - private static String errorMessageStringForMatch( - List> validPerPosition, - List signature, - AbstractFunctionTestCase.PositionalErrorMessageSupplier positionalErrorMessageSupplier - ) { - boolean invalid = false; - for (int i = 0; i < signature.size() && invalid == false; i++) { - // Need to check for nulls and bad parameters in order - if (signature.get(i) == DataType.NULL) { - return TypeResolutions.ParamOrdinal.fromIndex(i).name().toLowerCase(Locale.ROOT) - + " argument of [" - + sourceForSignature(signature) - + "] cannot be null, received []"; - } - if (validPerPosition.get(i).contains(signature.get(i)) == false) { - // Map expressions have different error messages - if (i == 2) { - return format(null, "third argument of [{}] must be a map expression, received []", sourceForSignature(signature)); - } - break; - } - } - - try { - return typeErrorMessage(true, validPerPosition, signature, positionalErrorMessageSupplier); - } catch (IllegalStateException e) { - // This means all the positional args were okay, so the expected error is for nulls or from the combination - return EsqlBinaryComparison.formatIncompatibleTypesMessage(signature.get(0), signature.get(1), sourceForSignature(signature)); - } - } - - private static final String FIELD_TYPE_ERROR_STRING = - "keyword, text, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version"; - - private static final String QUERY_TYPE_ERROR_STRING = - "keyword, boolean, date, date_nanos, double, integer, ip, long, unsigned_long, version"; -} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java index cb8833f00a694..1c64db23ad0f7 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchTests.java @@ -73,7 +73,7 @@ private static List addFunctionNamedParams(List args) { - Match match = new Match(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); + Match match = new Match(source, List.of(args.get(0)), args.get(1), args.size() > 2 ? args.get(2) : null); // We need to add the QueryBuilder to the match expression, as it is used to implement equals() and hashCode() and // thus test the serialization methods. But we can only do this if the parameters make sense . if (args.get(0) instanceof FieldAttribute && args.get(1).foldable()) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchTests.java index e14abda61ca63..67629613d9ba8 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MultiMatchTests.java @@ -34,8 +34,7 @@ public MultiMatchTests(@Name("TestCase") Supplier tes @Override protected Expression build(Source source, List args) { - // Note we are reversing the order of arguments here. - MultiMatch mm = new MultiMatch(source, args.get(1), List.of(args.get(0)), args.get(2)); + Match mm = new Match(source, List.of(args.get(0)), args.get(1), args.get(2)); // We need to add the QueryBuilder to the multi_match expression, as it is used to implement equals() and hashCode() and // thus test the serialization methods. But we can only do this if the parameters make sense . if (mm.query().foldable() && mm.fields().stream().allMatch(field -> field instanceof FieldAttribute)) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/TermTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/TermTests.java index eca246e20452c..c675661f5c6ba 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/TermTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/TermTests.java @@ -122,6 +122,6 @@ private static String matchTypeErrorSupplier(boolean includeOrdinal, List args) { - return new Match(source, args.get(0), args.get(1), args.size() > 2 ? args.get(2) : null); + return new Match(source, List.of(args.get(0)), args.get(1), args.size() > 2 ? args.get(2) : null); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java index b7d1243759493..00f88f2a02cc4 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java @@ -21,12 +21,13 @@ import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.MatchQueryBuilder; -import org.elasticsearch.index.query.MultiMatchQueryBuilder; +import org.elasticsearch.index.query.MultiFieldMatchQueryBuilder; import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryStringQueryBuilder; import org.elasticsearch.index.query.RangeQueryBuilder; import org.elasticsearch.index.query.SearchExecutionContext; +import org.elasticsearch.index.query.ZeroTermsQueryOption; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.search.vectors.KnnVectorQueryBuilder; import org.elasticsearch.search.vectors.RescoreVectorBuilder; @@ -1278,7 +1279,6 @@ public void testMatchOptionsPushDown() { var fieldExtract = as(project.child(), FieldExtractExec.class); var actualLuceneQuery = as(fieldExtract.child(), EsQueryExec.class).query(); - Source filterSource = new Source(4, 8, "emp_no > 10000"); var expectedLuceneQuery = new MatchQueryBuilder("first_name", "Anna").fuzziness(Fuzziness.AUTO) .prefixLength(3) .maxExpansions(10) @@ -1333,31 +1333,20 @@ public void testQStrOptionsPushDown() { public void testMultiMatchOptionsPushDown() { String query = """ from test - | where MULTI_MATCH("Anna", first_name, last_name, {"fuzzy_rewrite": "constant_score", "slop": 10, "analyzer": "auto", - "auto_generate_synonyms_phrase_query": "false", "fuzziness": "auto", "fuzzy_transpositions": false, "lenient": "false", - "max_expansions": 10, "minimum_should_match": 3, "operator": "AND", "prefix_length": 20, "tie_breaker": 1.0, - "type": "best_fields", "boost": 2.0}) + | where MATCH(first_name, last_name, "Anna", {"auto_generate_synonyms_phrase_query": "false", + "minimum_should_match": 3, "operator": "AND", "boost": 2.0, "zero_terms_query": "none"}) """; var plan = plannerOptimizer.plan(query); AtomicReference planStr = new AtomicReference<>(); plan.forEachDown(EsQueryExec.class, result -> planStr.set(result.query().toString())); - var expectedQuery = new MultiMatchQueryBuilder("Anna").fields(Map.of("first_name", 1.0f, "last_name", 1.0f)) - .slop(10) + var expectedQuery = MultiFieldMatchQueryBuilder.create("Anna", "first_name", "last_name") .boost(2.0f) - .analyzer("auto") .autoGenerateSynonymsPhraseQuery(false) .operator(Operator.fromString("AND")) - .fuzziness(Fuzziness.fromString("auto")) - .fuzzyRewrite("constant_score") - .fuzzyTranspositions(false) - .lenient(false) - .type("best_fields") - .maxExpansions(10) - .minimumShouldMatch("3") - .prefixLength(20) - .tieBreaker(1.0f); + .zeroTermsQuery(ZeroTermsQueryOption.readFromString("none")) + .minimumShouldMatch("3"); assertThat(expectedQuery.toString(), is(planStr.get())); } @@ -1964,7 +1953,8 @@ public void testMatchFunctionWithStatsWherePushable() { var agg = as(limit.child(), AggregateExec.class); var exchange = as(agg.child(), ExchangeExec.class); var stats = as(exchange.child(), EsStatsQueryExec.class); - QueryBuilder expected = new MatchQueryBuilder("last_name", "Smith").lenient(true); + var expected = new MatchQueryBuilder("last_name", "Smith"); + expected = expected.lenient(true); assertThat(stats.query().toString(), equalTo(expected.toString())); } @@ -1984,7 +1974,8 @@ public void testMatchFunctionWithStatsPushableAndNonPushableCondition() { assertTrue(filter.condition() instanceof GreaterThan); var fieldExtract = as(filter.child(), FieldExtractExec.class); var esQuery = as(fieldExtract.child(), EsQueryExec.class); - QueryBuilder expected = new MatchQueryBuilder("last_name", "Smith").lenient(true); + var expected = new MatchQueryBuilder("last_name", "Smith"); + expected = expected.lenient(true); assertThat(esQuery.query().toString(), equalTo(expected.toString())); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index 7795bf5c2d9ff..5ed975400f77b 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -57,7 +57,6 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.ToPartial; import org.elasticsearch.xpack.esql.expression.function.aggregate.Values; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; -import org.elasticsearch.xpack.esql.expression.function.fulltext.MultiMatch; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; import org.elasticsearch.xpack.esql.expression.function.grouping.Categorize; import org.elasticsearch.xpack.esql.expression.function.scalar.convert.ToDouble; @@ -7342,12 +7341,12 @@ public void testFunctionNamedParamsAsFunctionArgument() { public void testFunctionNamedParamsAsFunctionArgument1() { var query = """ from test - | WHERE MULTI_MATCH("Anna Smith", first_name, last_name, {"minimum_should_match": 2.0}) + | WHERE MATCH(first_name, last_name, "Anna Smith", {"minimum_should_match": 2.0}) """; var plan = optimizedPlan(query); Limit limit = as(plan, Limit.class); Filter filter = as(limit.child(), Filter.class); - MultiMatch match = as(filter.condition(), MultiMatch.class); + Match match = as(filter.condition(), Match.class); MapExpression me = as(match.options(), MapExpression.class); assertEquals(1, me.entryExpressions().size()); EntryExpression ee = as(me.entryExpressions().get(0), EntryExpression.class); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java index 99eded20b1687..b503d0450d015 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/PhysicalPlanOptimizerTests.java @@ -7904,8 +7904,11 @@ public void testScore() { Filter filter = as(limit.child(), Filter.class); Match match = as(filter.condition(), Match.class); - assertTrue(match.field() instanceof FieldAttribute); - assertEquals("first_name", ((FieldAttribute) match.field()).field().getName()); + var fields = match.fields(); + assertEquals(1, fields.size()); + var field = fields.getFirst(); + assertTrue(field instanceof FieldAttribute); + assertEquals("first_name", ((FieldAttribute) field).field().getName()); EsRelation esRelation = as(filter.child(), EsRelation.class); assertTrue(esRelation.optimized()); @@ -7936,8 +7939,11 @@ public void testScoreTopN() { Filter filter = as(topN.child(), Filter.class); Match match = as(filter.condition(), Match.class); - assertTrue(match.field() instanceof FieldAttribute); - assertEquals("first_name", ((FieldAttribute) match.field()).field().getName()); + var fields = match.fields(); + assertEquals(1, fields.size()); + var field = fields.getFirst(); + assertTrue(field instanceof FieldAttribute); + assertEquals("first_name", ((FieldAttribute) field).field().getName()); EsRelation esRelation = as(filter.child(), EsRelation.class); assertTrue(esRelation.optimized()); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineFiltersTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineFiltersTests.java index ca975e1e09954..bbca9a63024a6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineFiltersTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/rules/logical/PushDownAndCombineFiltersTests.java @@ -262,11 +262,11 @@ public void testPushDownFilterPastCompletion() { LessThan conditionB = lessThanOf(getFieldAttribute("b"), TWO); Match conditionCompletion = new Match( EMPTY, - completion.targetField(), + List.of(completion.targetField()), randomLiteral(DataType.TEXT), - mock(Expression.class), - mock(QueryBuilder.class) + mock(Expression.class) ); + conditionCompletion.replaceQueryBuilder(mock(QueryBuilder.class)); Filter filterB = new Filter(EMPTY, completion, new And(EMPTY, conditionB, conditionCompletion)); LogicalPlan expectedOptimizedPlan = new Filter( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java index cb5c531939498..6c6971ced141d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/StatementParserTests.java @@ -2515,7 +2515,9 @@ public void testMatchOperatorConstantQueryString() { var plan = statement("FROM test | WHERE field:\"value\""); var filter = as(plan, Filter.class); var match = (MatchOperator) filter.condition(); - var matchField = (UnresolvedAttribute) match.field(); + var fields = match.fields(); + assertEquals(1, fields.size()); + var matchField = (UnresolvedAttribute) fields.getFirst(); assertThat(matchField.name(), equalTo("field")); assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("value"))); } @@ -2559,7 +2561,10 @@ public void testMatchOperatorFieldCasting() { var plan = statement("FROM test | WHERE field::int : \"value\""); var filter = as(plan, Filter.class); var match = (MatchOperator) filter.condition(); - var toInteger = (ToInteger) match.field(); + var fields = match.fields(); + assertEquals(1, fields.size()); + ; + var toInteger = (ToInteger) fields.getFirst(); var matchField = (UnresolvedAttribute) toInteger.field(); assertThat(matchField.name(), equalTo("field")); assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("value"))); @@ -3273,80 +3278,98 @@ public void testValidFork() { var fork = as(plan, Fork.class); var subPlans = fork.children(); - // first subplan - var eval = as(subPlans.get(0), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork1")))); - var limit = as(eval.child(), Limit.class); - assertThat(limit.limit(), instanceOf(Literal.class)); - assertThat(((Literal) limit.limit()).value(), equalTo(11)); - var filter = as(limit.child(), Filter.class); - var match = (MatchOperator) filter.condition(); - var matchField = (UnresolvedAttribute) match.field(); - assertThat(matchField.name(), equalTo("a")); - assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("baz"))); - - // second subplan - eval = as(subPlans.get(1), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork2")))); - var orderBy = as(eval.child(), OrderBy.class); - assertThat(orderBy.order().size(), equalTo(1)); - Order order = orderBy.order().get(0); - assertThat(order.child(), instanceOf(UnresolvedAttribute.class)); - assertThat(((UnresolvedAttribute) order.child()).name(), equalTo("b")); - filter = as(orderBy.child(), Filter.class); - match = (MatchOperator) filter.condition(); - matchField = (UnresolvedAttribute) match.field(); - assertThat(matchField.name(), equalTo("b")); - assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("bar"))); - - // third subplan - eval = as(subPlans.get(2), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork3")))); - filter = as(eval.child(), Filter.class); - match = (MatchOperator) filter.condition(); - matchField = (UnresolvedAttribute) match.field(); - assertThat(matchField.name(), equalTo("c")); - assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("bat"))); - - // fourth subplan - eval = as(subPlans.get(3), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork4")))); - orderBy = as(eval.child(), OrderBy.class); - assertThat(orderBy.order().size(), equalTo(1)); - order = orderBy.order().get(0); - assertThat(order.child(), instanceOf(UnresolvedAttribute.class)); - assertThat(((UnresolvedAttribute) order.child()).name(), equalTo("c")); + { + // first subplan + var eval = as(subPlans.get(0), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork1")))); + var limit = as(eval.child(), Limit.class); + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(11)); + var filter = as(limit.child(), Filter.class); + var match = (MatchOperator) filter.condition(); + var fields = match.fields(); + assertEquals(1, fields.size()); + var matchField = (UnresolvedAttribute) fields.getFirst(); + assertThat(matchField.name(), equalTo("a")); + assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("baz"))); + } - // fifth subplan - eval = as(subPlans.get(4), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork5")))); - limit = as(eval.child(), Limit.class); - assertThat(limit.limit(), instanceOf(Literal.class)); - assertThat(((Literal) limit.limit()).value(), equalTo(5)); + { + // second subplan + var eval = as(subPlans.get(1), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork2")))); + var orderBy = as(eval.child(), OrderBy.class); + assertThat(orderBy.order().size(), equalTo(1)); + Order order = orderBy.order().get(0); + assertThat(order.child(), instanceOf(UnresolvedAttribute.class)); + assertThat(((UnresolvedAttribute) order.child()).name(), equalTo("b")); + var filter = as(orderBy.child(), Filter.class); + var match = (MatchOperator) filter.condition(); + var fields = match.fields(); + assertEquals(1, fields.size()); + var matchField = (UnresolvedAttribute) fields.getFirst(); + assertThat(matchField.name(), equalTo("b")); + assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("bar"))); + } + + { + // third subplan + var eval = as(subPlans.get(2), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork3")))); + var filter = as(eval.child(), Filter.class); + var match = (MatchOperator) filter.condition(); + var fields = match.fields(); + assertEquals(1, fields.size()); + var matchField = (UnresolvedAttribute) fields.getFirst(); + assertThat(matchField.name(), equalTo("c")); + assertThat(match.query().fold(FoldContext.small()), equalTo(BytesRefs.toBytesRef("bat"))); + } + + { + // fourth subplan + var eval = as(subPlans.get(3), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork4")))); + var orderBy = as(eval.child(), OrderBy.class); + assertThat(orderBy.order().size(), equalTo(1)); + var order = orderBy.order().get(0); + assertThat(order.child(), instanceOf(UnresolvedAttribute.class)); + assertThat(((UnresolvedAttribute) order.child()).name(), equalTo("c")); + } + + { + // fifth subplan + var eval = as(subPlans.get(4), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork5")))); + var limit = as(eval.child(), Limit.class); + assertThat(limit.limit(), instanceOf(Literal.class)); + assertThat(((Literal) limit.limit()).value(), equalTo(5)); + } - // sixth subplan - eval = as(subPlans.get(5), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork6")))); - eval = as(eval.child(), Eval.class); - assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("xyz", literalString("abc")))); - - Aggregate aggregate = as(eval.child(), Aggregate.class); - assertThat(aggregate.aggregates().size(), equalTo(2)); - var alias = as(aggregate.aggregates().get(0), Alias.class); - assertThat(alias.name(), equalTo("x")); - assertThat(as(alias.child(), UnresolvedFunction.class).name(), equalTo("MIN")); - - alias = as(aggregate.aggregates().get(1), Alias.class); - assertThat(alias.name(), equalTo("y")); - var filteredExp = as(alias.child(), FilteredExpression.class); - assertThat(as(filteredExp.delegate(), UnresolvedFunction.class).name(), equalTo("MAX")); - var greaterThan = as(filteredExp.filter(), GreaterThan.class); - assertThat(as(greaterThan.left(), UnresolvedAttribute.class).name(), equalTo("d")); - assertThat(as(greaterThan.right(), Literal.class).value(), equalTo(1000)); - - var dissect = as(aggregate.child(), Dissect.class); - assertThat(as(dissect.input(), UnresolvedAttribute.class).name(), equalTo("a")); - assertThat(dissect.parser().pattern(), equalTo("%{d} %{e} %{f}")); + { + // sixth subplan + var eval = as(subPlans.get(5), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("_fork", literalString("fork6")))); + eval = as(eval.child(), Eval.class); + assertThat(as(eval.fields().get(0), Alias.class), equalTo(alias("xyz", literalString("abc")))); + + Aggregate aggregate = as(eval.child(), Aggregate.class); + assertThat(aggregate.aggregates().size(), equalTo(2)); + var alias = as(aggregate.aggregates().get(0), Alias.class); + assertThat(alias.name(), equalTo("x")); + assertThat(as(alias.child(), UnresolvedFunction.class).name(), equalTo("MIN")); + + alias = as(aggregate.aggregates().get(1), Alias.class); + assertThat(alias.name(), equalTo("y")); + var filteredExp = as(alias.child(), FilteredExpression.class); + assertThat(as(filteredExp.delegate(), UnresolvedFunction.class).name(), equalTo("MAX")); + var greaterThan = as(filteredExp.filter(), GreaterThan.class); + assertThat(as(greaterThan.left(), UnresolvedAttribute.class).name(), equalTo("d")); + assertThat(as(greaterThan.right(), Literal.class).value(), equalTo(1000)); + + var dissect = as(aggregate.child(), Dissect.class); + assertThat(as(dissect.input(), UnresolvedAttribute.class).name(), equalTo("a")); + assertThat(dissect.parser().pattern(), equalTo("%{d} %{e} %{f}")); + } } public void testForkAllReleasedCommands() { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQueryTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQueryTests.java deleted file mode 100644 index 81308a7538796..0000000000000 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/MultiMatchQueryTests.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -package org.elasticsearch.xpack.esql.querydsl.query; - -import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.index.query.MultiMatchQueryBuilder; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.util.StringUtils; - -import java.util.Map; - -import static org.hamcrest.Matchers.equalTo; - -public class MultiMatchQueryTests extends ESTestCase { - - public void testQueryBuilding() { - MultiMatchQueryBuilder qb = getBuilder(Map.of("lenient", true)); - assertThat(qb.lenient(), equalTo(true)); - - qb = getBuilder(Map.of("type", "best_fields")); - assertThat(qb.getType(), equalTo(MultiMatchQueryBuilder.Type.BEST_FIELDS)); - - Exception e = expectThrows(IllegalArgumentException.class, () -> getBuilder(Map.of("pizza", "yummy"))); - assertThat(e.getMessage(), equalTo("illegal multi_match option [pizza]")); - - e = expectThrows(ElasticsearchParseException.class, () -> getBuilder(Map.of("type", "aoeu"))); - assertThat(e.getMessage(), equalTo("failed to parse [multi_match] query type [aoeu]. unknown type.")); - } - - private static MultiMatchQueryBuilder getBuilder(Map options) { - final Source source = new Source(1, 1, StringUtils.EMPTY); - final MultiMatchQuery mmq = new MultiMatchQuery(source, "eggplant", Map.of("bar", 1.0f, "foo", 1.0f), options); - return (MultiMatchQueryBuilder) mmq.asBuilder(); - } - - public void testToString() { - final Source source = new Source(1, 1, StringUtils.EMPTY); - final MultiMatchQuery mmq = new MultiMatchQuery(source, "eggplant", Map.of("bar", 1.0f, "foo", 1.0f), null); - assertEquals("MultiMatchQuery@1:2[{bar=1.0, foo=1.0}:eggplant]", mmq.toString()); - } -}