diff --git a/docs/sphinx/api.rst b/docs/sphinx/api.rst index 812511f87..96aa91e3e 100644 --- a/docs/sphinx/api.rst +++ b/docs/sphinx/api.rst @@ -24,6 +24,7 @@ arguments are required for all calls. api/dangling-indices api/enrich-policies api/eql + api/esql api/fleet api/graph-explore api/index-lifecycle-management diff --git a/docs/sphinx/api/esql.rst b/docs/sphinx/api/esql.rst new file mode 100644 index 000000000..f38dda764 --- /dev/null +++ b/docs/sphinx/api/esql.rst @@ -0,0 +1,9 @@ +.. _esql: + +ES|QL +----- +.. py:module:: elasticsearch.client + :noindex: + +.. autoclass:: EsqlClient + :members: \ No newline at end of file diff --git a/elasticsearch/_async/client/__init__.py b/elasticsearch/_async/client/__init__.py index 86c9ac1f5..9f8f24cbd 100644 --- a/elasticsearch/_async/client/__init__.py +++ b/elasticsearch/_async/client/__init__.py @@ -49,6 +49,7 @@ from .dangling_indices import DanglingIndicesClient from .enrich import EnrichClient from .eql import EqlClient +from .esql import EsqlClient from .features import FeaturesClient from .fleet import FleetClient from .graph import GraphClient @@ -444,6 +445,7 @@ def __init__( self.dangling_indices = DanglingIndicesClient(self) self.enrich = EnrichClient(self) self.eql = EqlClient(self) + self.esql = EsqlClient(self) self.graph = GraphClient(self) self.ilm = IlmClient(self) self.license = LicenseClient(self) diff --git a/elasticsearch/_async/client/esql.py b/elasticsearch/_async/client/esql.py new file mode 100644 index 000000000..9fe070f75 --- /dev/null +++ b/elasticsearch/_async/client/esql.py @@ -0,0 +1,99 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import typing as t + +from elastic_transport import ObjectApiResponse + +from ._base import NamespacedClient +from .utils import _rewrite_parameters + + +class EsqlClient(NamespacedClient): + @_rewrite_parameters( + body_fields=("query", "columnar", "filter", "locale", "params"), + ignore_deprecated_options={"params"}, + ) + async def query( + self, + *, + query: t.Optional[str] = None, + columnar: t.Optional[bool] = None, + delimiter: t.Optional[str] = None, + error_trace: t.Optional[bool] = None, + filter: t.Optional[t.Mapping[str, t.Any]] = None, + filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None, + format: t.Optional[str] = None, + human: t.Optional[bool] = None, + locale: t.Optional[str] = None, + params: t.Optional[t.Sequence[t.Union[None, bool, float, int, str]]] = None, + pretty: t.Optional[bool] = None, + body: t.Optional[t.Dict[str, t.Any]] = None, + ) -> ObjectApiResponse[t.Any]: + """ + Executes an ESQL request + + ``_ + + :param query: The ES|QL query API accepts an ES|QL query string in the query + parameter, runs it, and returns the results. + :param columnar: By default, ES|QL returns results as rows. For example, FROM + returns each individual document as one row. For the JSON, YAML, CBOR and + smile formats, ES|QL can return the results in a columnar fashion where one + row represents all the values of a certain column in the results. + :param delimiter: The character to use between values within a CSV row. Only + valid for the CSV format. + :param filter: Specify a Query DSL query in the filter parameter to filter the + set of documents that an ES|QL query runs on. + :param format: A short version of the Accept header, e.g. json, yaml. + :param locale: + :param params: To avoid any attempts of hacking or code injection, extract the + values in a separate list of parameters. Use question mark placeholders (?) + in the query string for each of the parameters. + """ + if query is None and body is None: + raise ValueError("Empty value passed for parameter 'query'") + __path = "/_query" + __query: t.Dict[str, t.Any] = {} + __body: t.Dict[str, t.Any] = body if body is not None else {} + if delimiter is not None: + __query["delimiter"] = delimiter + if error_trace is not None: + __query["error_trace"] = error_trace + if filter_path is not None: + __query["filter_path"] = filter_path + if format is not None: + __query["format"] = format + if human is not None: + __query["human"] = human + if pretty is not None: + __query["pretty"] = pretty + if not __body: + if query is not None: + __body["query"] = query + if columnar is not None: + __body["columnar"] = columnar + if filter is not None: + __body["filter"] = filter + if locale is not None: + __body["locale"] = locale + if params is not None: + __body["params"] = params + __headers = {"accept": "application/json", "content-type": "application/json"} + return await self.perform_request( # type: ignore[return-value] + "POST", __path, params=__query, headers=__headers, body=__body + ) diff --git a/elasticsearch/_sync/client/__init__.py b/elasticsearch/_sync/client/__init__.py index e2bdb6380..2952b8255 100644 --- a/elasticsearch/_sync/client/__init__.py +++ b/elasticsearch/_sync/client/__init__.py @@ -49,6 +49,7 @@ from .dangling_indices import DanglingIndicesClient from .enrich import EnrichClient from .eql import EqlClient +from .esql import EsqlClient from .features import FeaturesClient from .fleet import FleetClient from .graph import GraphClient @@ -444,6 +445,7 @@ def __init__( self.dangling_indices = DanglingIndicesClient(self) self.enrich = EnrichClient(self) self.eql = EqlClient(self) + self.esql = EsqlClient(self) self.graph = GraphClient(self) self.ilm = IlmClient(self) self.license = LicenseClient(self) diff --git a/elasticsearch/_sync/client/esql.py b/elasticsearch/_sync/client/esql.py new file mode 100644 index 000000000..250b0492a --- /dev/null +++ b/elasticsearch/_sync/client/esql.py @@ -0,0 +1,99 @@ +# Licensed to Elasticsearch B.V. under one or more contributor +# license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright +# ownership. Elasticsearch B.V. licenses this file to you under +# the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +import typing as t + +from elastic_transport import ObjectApiResponse + +from ._base import NamespacedClient +from .utils import _rewrite_parameters + + +class EsqlClient(NamespacedClient): + @_rewrite_parameters( + body_fields=("query", "columnar", "filter", "locale", "params"), + ignore_deprecated_options={"params"}, + ) + def query( + self, + *, + query: t.Optional[str] = None, + columnar: t.Optional[bool] = None, + delimiter: t.Optional[str] = None, + error_trace: t.Optional[bool] = None, + filter: t.Optional[t.Mapping[str, t.Any]] = None, + filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None, + format: t.Optional[str] = None, + human: t.Optional[bool] = None, + locale: t.Optional[str] = None, + params: t.Optional[t.Sequence[t.Union[None, bool, float, int, str]]] = None, + pretty: t.Optional[bool] = None, + body: t.Optional[t.Dict[str, t.Any]] = None, + ) -> ObjectApiResponse[t.Any]: + """ + Executes an ESQL request + + ``_ + + :param query: The ES|QL query API accepts an ES|QL query string in the query + parameter, runs it, and returns the results. + :param columnar: By default, ES|QL returns results as rows. For example, FROM + returns each individual document as one row. For the JSON, YAML, CBOR and + smile formats, ES|QL can return the results in a columnar fashion where one + row represents all the values of a certain column in the results. + :param delimiter: The character to use between values within a CSV row. Only + valid for the CSV format. + :param filter: Specify a Query DSL query in the filter parameter to filter the + set of documents that an ES|QL query runs on. + :param format: A short version of the Accept header, e.g. json, yaml. + :param locale: + :param params: To avoid any attempts of hacking or code injection, extract the + values in a separate list of parameters. Use question mark placeholders (?) + in the query string for each of the parameters. + """ + if query is None and body is None: + raise ValueError("Empty value passed for parameter 'query'") + __path = "/_query" + __query: t.Dict[str, t.Any] = {} + __body: t.Dict[str, t.Any] = body if body is not None else {} + if delimiter is not None: + __query["delimiter"] = delimiter + if error_trace is not None: + __query["error_trace"] = error_trace + if filter_path is not None: + __query["filter_path"] = filter_path + if format is not None: + __query["format"] = format + if human is not None: + __query["human"] = human + if pretty is not None: + __query["pretty"] = pretty + if not __body: + if query is not None: + __body["query"] = query + if columnar is not None: + __body["columnar"] = columnar + if filter is not None: + __body["filter"] = filter + if locale is not None: + __body["locale"] = locale + if params is not None: + __body["params"] = params + __headers = {"accept": "application/json", "content-type": "application/json"} + return self.perform_request( # type: ignore[return-value] + "POST", __path, params=__query, headers=__headers, body=__body + ) diff --git a/elasticsearch/client.py b/elasticsearch/client.py index d4436f480..078648167 100644 --- a/elasticsearch/client.py +++ b/elasticsearch/client.py @@ -32,6 +32,7 @@ ) from ._sync.client.enrich import EnrichClient as EnrichClient # noqa: F401 from ._sync.client.eql import EqlClient as EqlClient # noqa: F401 +from ._sync.client.esql import EsqlClient as EsqlClient # noqa: F401 from ._sync.client.features import FeaturesClient as FeaturesClient # noqa: F401 from ._sync.client.fleet import FleetClient as FleetClient # noqa: F401 from ._sync.client.graph import GraphClient as GraphClient # noqa: F401