diff --git a/docs/changelog/128925.yaml b/docs/changelog/128925.yaml new file mode 100644 index 0000000000000..dd41f7366ddd1 --- /dev/null +++ b/docs/changelog/128925.yaml @@ -0,0 +1,5 @@ +pr: 128925 +summary: ES|QL - Add `match_phrase` full text function (tech preview) +area: ES|QL +type: enhancement +issues: [] diff --git a/docs/reference/query-languages/esql/_snippets/functions/description/match_phrase.md b/docs/reference/query-languages/esql/_snippets/functions/description/match_phrase.md index 6970bbfb1a3e2..7907e2a06c736 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/description/match_phrase.md +++ b/docs/reference/query-languages/esql/_snippets/functions/description/match_phrase.md @@ -2,5 +2,5 @@ **Description** -Use `MATCH_PHRASE` to perform a [match_phrase query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-match-query-phrase) on the specified field. Using `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL. MatchPhrase can be used on [text](/reference/elasticsearch/mapping-reference/text.md) fields, as well as other field types like keyword, boolean, or date types. MatchPhrase is not supported for [semantic_text](/reference/elasticsearch/mapping-reference/semantic-text.md) or numeric types. MatchPhrase can use [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params) to specify additional options for the match_phrase query. All [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) query parameters are supported. `MATCH_PHRASE` returns true if the provided query matches the row. +Use `MATCH_PHRASE` to perform a [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) on the specified field. Using `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL. MatchPhrase can be used on [text](/reference/elasticsearch/mapping-reference/text.md) fields, as well as other field types like keyword, boolean, or date types. MatchPhrase is not supported for [semantic_text](/reference/elasticsearch/mapping-reference/semantic-text.md) or numeric types. MatchPhrase can use [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params) to specify additional options for the match_phrase query. All [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) query parameters are supported. `MATCH_PHRASE` returns true if the provided query matches the row. diff --git a/docs/reference/query-languages/esql/_snippets/functions/parameters/match_phrase.md b/docs/reference/query-languages/esql/_snippets/functions/parameters/match_phrase.md index baf89625dc51c..3758872005aaa 100644 --- a/docs/reference/query-languages/esql/_snippets/functions/parameters/match_phrase.md +++ b/docs/reference/query-languages/esql/_snippets/functions/parameters/match_phrase.md @@ -9,5 +9,5 @@ : Value to find in the provided field. `options` -: (Optional) MatchPhrase additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [match_phrase query](/reference/query-languages/query-dsl/query-dsl-match-query.md#query-dsl-match-query-phrase) for more information. +: (Optional) MatchPhrase additional options as [function named parameters](/reference/query-languages/esql/esql-syntax.md#esql-function-named-params). See [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) for more information. diff --git a/docs/reference/query-languages/esql/_snippets/lists/search-functions.md b/docs/reference/query-languages/esql/_snippets/lists/search-functions.md index 8ceb0d2f99b90..b735d7e5b8574 100644 --- a/docs/reference/query-languages/esql/_snippets/lists/search-functions.md +++ b/docs/reference/query-languages/esql/_snippets/lists/search-functions.md @@ -1,7 +1,6 @@ * [preview] [`KQL`](../../functions-operators/search-functions.md#esql-kql) * [preview] [`MATCH`](../../functions-operators/search-functions.md#esql-match) - % * [preview] [ - `MATCH_PHRASE`](../../functions-operators/search-functions.md#esql-match-phrase) +* [preview] [`MATCH_PHRASE`](../../functions-operators/search-functions.md#esql-match_phrase) * [preview] [`QSTR`](../../functions-operators/search-functions.md#esql-qstr) % * [preview] [ `TERM`](../../functions-operators/search-functions.md#esql-term) diff --git a/docs/reference/query-languages/esql/functions-operators/search-functions.md b/docs/reference/query-languages/esql/functions-operators/search-functions.md index 7406aee8f737d..44207fbf30ce7 100644 --- a/docs/reference/query-languages/esql/functions-operators/search-functions.md +++ b/docs/reference/query-languages/esql/functions-operators/search-functions.md @@ -36,9 +36,8 @@ for information on the limitations of full text search. :::{include} ../_snippets/functions/layout/match.md ::: -% MATCH_PHRASE is currently hidden -% :::{include} ../_snippets/functions/layout/match_phrase.md -% ::: +:::{include} ../_snippets/functions/layout/match_phrase.md +::: :::{include} ../_snippets/functions/layout/qstr.md ::: diff --git a/docs/reference/query-languages/esql/kibana/definition/functions/match_phrase.json b/docs/reference/query-languages/esql/kibana/definition/functions/match_phrase.json index fee736b505793..924afa7985ebf 100644 --- a/docs/reference/query-languages/esql/kibana/definition/functions/match_phrase.json +++ b/docs/reference/query-languages/esql/kibana/definition/functions/match_phrase.json @@ -2,7 +2,7 @@ "comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", "type" : "scalar", "name" : "match_phrase", - "description" : "Use `MATCH_PHRASE` to perform a match_phrase query on the specified field.\nUsing `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL.\n\nMatchPhrase can be used on text fields, as well as other field types like keyword, boolean, or date types.\nMatchPhrase is not supported for semantic_text or numeric types.\n\nMatchPhrase can use function named parameters to specify additional options for the\nmatch_phrase query.\nAll `match_phrase` query parameters are supported.\n\n`MATCH_PHRASE` returns true if the provided query matches the row.", + "description" : "Use `MATCH_PHRASE` to perform a `match_phrase` on the\nspecified field.\nUsing `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL.\n\nMatchPhrase can be used on text fields, as well as other field types like keyword, boolean, or date types.\nMatchPhrase is not supported for semantic_text or numeric types.\n\nMatchPhrase can use function named parameters to specify additional options for the\nmatch_phrase query.\nAll `match_phrase` query parameters are supported.\n\n`MATCH_PHRASE` returns true if the provided query matches the row.", "signatures" : [ { "params" : [ @@ -23,7 +23,7 @@ "type" : "function_named_parameters", "mapParams" : "{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='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='slop', values=[1], description='Maximum number of positions allowed between matching tokens. Defaults to 0. Transposed terms have a slop of 2.'}", "optional" : true, - "description" : "(Optional) MatchPhrase additional options as <>. See <> for more information." + "description" : "(Optional) MatchPhrase additional options as <>. See [`match_phrase`](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query-phrase) for more information." } ], "variadic" : false, @@ -48,7 +48,7 @@ "type" : "function_named_parameters", "mapParams" : "{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='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='slop', values=[1], description='Maximum number of positions allowed between matching tokens. Defaults to 0. Transposed terms have a slop of 2.'}", "optional" : true, - "description" : "(Optional) MatchPhrase additional options as <>. See <> for more information." + "description" : "(Optional) MatchPhrase additional options as <>. See [`match_phrase`](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query-phrase) for more information." } ], "variadic" : false, diff --git a/docs/reference/query-languages/esql/kibana/docs/functions/match_phrase.md b/docs/reference/query-languages/esql/kibana/docs/functions/match_phrase.md index ee8552563277c..3a768ddee150b 100644 --- a/docs/reference/query-languages/esql/kibana/docs/functions/match_phrase.md +++ b/docs/reference/query-languages/esql/kibana/docs/functions/match_phrase.md @@ -1,7 +1,8 @@ % This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. ### MATCH PHRASE -Use `MATCH_PHRASE` to perform a [match_phrase query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query#query-dsl-match-query-phrase) on the specified field. +Use `MATCH_PHRASE` to perform a [`match_phrase`](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query-phrase) on the +specified field. Using `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL. MatchPhrase can be used on [text](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/text) fields, as well as other field types like keyword, boolean, or date types. diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchPhraseFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchPhraseFunctionIT.java index 58ba2a5313063..44f28e0c9ea93 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchPhraseFunctionIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchPhraseFunctionIT.java @@ -13,9 +13,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.xpack.esql.VerificationException; import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; -import org.elasticsearch.xpack.esql.action.EsqlCapabilities; -import org.elasticsearch.xpack.esql.action.EsqlQueryRequest; -import org.elasticsearch.xpack.esql.action.EsqlQueryResponse; import org.hamcrest.Matchers; import org.junit.Before; @@ -34,12 +31,6 @@ public void setupIndex() { createAndPopulateIndex(); } - @Override - protected EsqlQueryResponse run(EsqlQueryRequest request) { - assumeTrue("match_phrase function capability not available", EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()); - return super.run(request); - } - public void testSimpleWhereMatchPhrase() { var query = """ FROM test 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 c03908e3287f2..f6d27bcb628f0 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 @@ -50,12 +50,10 @@ public static List params() { params.add(new Object[] { "content:\"fox\"" }); params.add(new Object[] { "qstr(\"content: fox\")" }); params.add(new Object[] { "kql(\"content*: fox\")" }); + params.add(new Object[] { "match_phrase(content, \"fox\")" }); if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { params.add(new Object[] { "term(content, \"fox\")" }); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - params.add(new Object[] { "match_phrase(content, \"fox\")" }); - } return params; } 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 8396965096e06..77fb1b077b3a6 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 @@ -1185,7 +1185,7 @@ public enum Cap { /** * MATCH PHRASE function */ - MATCH_PHRASE_FUNCTION(Build.current().isSnapshot()); + MATCH_PHRASE_FUNCTION; private final boolean enabled; 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 b47594cedb08f..18c0a22589baa 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 @@ -23,15 +23,12 @@ public static List getNamedWriteables() { entries.add(Match.ENTRY); entries.add(MultiMatch.ENTRY); entries.add(Kql.ENTRY); + entries.add(MatchPhrase.ENTRY); if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { entries.add(Term.ENTRY); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - entries.add(MatchPhrase.ENTRY); - } - return Collections.unmodifiableList(entries); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhrase.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhrase.java index 471619dfc771e..7682fff3eda16 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhrase.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhrase.java @@ -94,7 +94,8 @@ public class MatchPhrase extends FullTextFunction implements OptionalArgument, P returnType = "boolean", preview = true, description = """ - Use `MATCH_PHRASE` to perform a <> on the specified field. + Use `MATCH_PHRASE` to perform a [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) on the + specified field. Using `MATCH_PHRASE` is equivalent to using the `match_phrase` query in the Elasticsearch Query DSL. MatchPhrase can be used on <> fields, as well as other field types like keyword, boolean, or date types. @@ -149,7 +150,7 @@ public MatchPhrase( description = "Floating point number used to decrease or increase the relevance scores of the query. Defaults to 1.0." ) }, description = "(Optional) MatchPhrase additional options as <>." - + " See <> for more information.", + + " See [`match_phrase`](/reference/query-languages/query-dsl/query-dsl-match-query-phrase.md) for more information.", optional = true ) Expression options ) { 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 311d22c743248..b32a74cd66f41 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 @@ -1223,6 +1223,9 @@ public void testFieldBasedFullTextFunctions() throws Exception { checkFieldBasedWithNonIndexedColumn(":", "text : \"cat\"", "operator"); checkFieldBasedFunctionNotAllowedAfterCommands(":", "operator", "title : \"Meditation\""); + 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)"); @@ -1231,10 +1234,6 @@ public void testFieldBasedFullTextFunctions() throws Exception { checkFieldBasedWithNonIndexedColumn("Term", "term(text, \"cat\")", "function"); checkFieldBasedFunctionNotAllowedAfterCommands("Term", "function", "term(title, \"Meditation\")"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFieldBasedWithNonIndexedColumn("MatchPhrase", "match_phrase(text, \"cat\")", "function"); - checkFieldBasedFunctionNotAllowedAfterCommands("MatchPhrase", "function", "match_phrase(title, \"Meditation\")"); - } } private void checkFieldBasedFunctionNotAllowedAfterCommands(String functionName, String functionType, String functionInvocation) { @@ -1358,15 +1357,13 @@ public void testFullTextFunctionsOnlyAllowedInWhere() throws Exception { checkFullTextFunctionsOnlyAllowedInWhere(":", "title:\"Meditation\"", "operator"); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Meditation\")", "function"); checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Meditation\")", "function"); + checkFullTextFunctionsOnlyAllowedInWhere("MatchPhrase", "match_phrase(title, \"Meditation\")", "function"); 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.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFullTextFunctionsOnlyAllowedInWhere("MatchPhrase", "match_phrase(title, \"Meditation\")", "function"); - } } private void checkFullTextFunctionsOnlyAllowedInWhere(String functionName, String functionInvocation, String functionType) @@ -1396,15 +1393,13 @@ public void testFullTextFunctionsDisjunctions() { checkWithFullTextFunctionsDisjunctions("title : \"Meditation\""); 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\")"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkWithFullTextFunctionsDisjunctions("match_phrase(title, \"Meditation\")"); - } } private void checkWithFullTextFunctionsDisjunctions(String functionInvocation) { @@ -1460,15 +1455,13 @@ public void testFullTextFunctionsWithNonBooleanFunctions() { 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"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFullTextFunctionsWithNonBooleanFunctions("MatchPhrase", "match_phrase(title, \"Meditation\")", "function"); - } } private void checkFullTextFunctionsWithNonBooleanFunctions(String functionName, String functionInvocation, String functionType) { @@ -1530,15 +1523,13 @@ private void checkFullTextFunctionsWithNonBooleanFunctions(String functionName, 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\")"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - testFullTextFunctionTargetsExistingField("match_phrase(title, \"Meditation\")"); - } } private void testFullTextFunctionTargetsExistingField(String functionInvocation) throws Exception { @@ -2060,12 +2051,10 @@ public void testLookupJoinDataTypeMismatch() { public void testFullTextFunctionOptions() { checkOptionDataTypes(Match.ALLOWED_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.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkOptionDataTypes(MatchPhrase.ALLOWED_OPTIONS, "FROM test | WHERE MATCH_PHRASE(title, \"Jean\", {\"%s\": %s})"); - } } /** @@ -2120,15 +2109,13 @@ private static String exampleValueForType(DataType currentType) { 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\")"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - testFullTextFunctionsCurrentlyUnsupportedBehaviour("match_phrase(title, \"Meditation\")"); - } } private void testFullTextFunctionsCurrentlyUnsupportedBehaviour(String functionInvocation) throws Exception { @@ -2143,6 +2130,8 @@ public void testFullTextFunctionsNullArgs() throws Exception { checkFullTextFunctionNullArgs("match(title, null)", "second"); checkFullTextFunctionNullArgs("qstr(null)", ""); 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"); @@ -2151,10 +2140,6 @@ public void testFullTextFunctionsNullArgs() throws Exception { checkFullTextFunctionNullArgs("term(null, \"query\")", "first"); checkFullTextFunctionNullArgs("term(title, null)", "second"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFullTextFunctionNullArgs("match_phrase(null, \"query\")", "first"); - checkFullTextFunctionNullArgs("match_phrase(title, null)", "second"); - } } private void checkFullTextFunctionNullArgs(String functionInvocation, String argOrdinal) throws Exception { @@ -2168,6 +2153,7 @@ public void testFullTextFunctionsConstantQuery() throws Exception { checkFullTextFunctionsConstantQuery("match(title, category)", "second"); 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"); @@ -2175,9 +2161,6 @@ public void testFullTextFunctionsConstantQuery() throws Exception { if (EsqlCapabilities.Cap.TERM_FUNCTION.isEnabled()) { checkFullTextFunctionsConstantQuery("term(title, tags)", "second"); } - if (EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFullTextFunctionsConstantQuery("match_phrase(title, tags)", "second"); - } } private void checkFullTextFunctionsConstantQuery(String functionInvocation, String argOrdinal) throws Exception { @@ -2201,12 +2184,10 @@ public void testFullTextFunctionsInStats() { checkFullTextFunctionsInStats("title : \"Meditation\""); 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.MATCH_PHRASE_FUNCTION.isEnabled()) { - checkFullTextFunctionsInStats("match_phrase(title, \"Meditation\")"); - } } private void checkFullTextFunctionsInStats(String functionInvocation) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseTests.java index 496f269da9dc0..ce996962398bf 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/MatchPhraseTests.java @@ -11,7 +11,6 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.expression.FieldAttribute; import org.elasticsearch.xpack.esql.core.expression.Literal; @@ -23,7 +22,6 @@ import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; import org.elasticsearch.xpack.esql.io.stream.PlanStreamOutput; import org.elasticsearch.xpack.esql.optimizer.rules.physical.local.LucenePushdownPredicates; -import org.junit.Before; import java.util.ArrayList; import java.util.List; @@ -41,11 +39,6 @@ @FunctionName("match_phrase") public class MatchPhraseTests extends AbstractFunctionTestCase { - @Before - public void checkCapability() { - assumeTrue("MatchPhrase is not supported in this version of ESQL", EsqlCapabilities.Cap.MATCH_PHRASE_FUNCTION.isEnabled()); - } - public MatchPhraseTests(@Name("TestCase") Supplier testCaseSupplier) { this.testCase = testCaseSupplier.get(); } diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index 3aa39f6983249..14cf02e0bdcb3 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -130,7 +130,7 @@ setup: - match: {esql.functions.coalesce: $functions_coalesce} - gt: {esql.functions.categorize: $functions_categorize} # Testing for the entire function set isn't feasible, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 156} # check the "sister" test below for a likely update to the same esql.functions length check + - length: {esql.functions: 157} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version":