Skip to content

Commit 781734d

Browse files
[Backport 8.12] Add ES|QL API (#2407)
* Add ES|QL API (#2405) (cherry picked from commit 997d8a8) * Fix doc URLs --------- Co-authored-by: Quentin Pradet <quentin.pradet@elastic.co>
1 parent 336319d commit 781734d

File tree

7 files changed

+213
-0
lines changed

7 files changed

+213
-0
lines changed

docs/sphinx/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ arguments are required for all calls.
2424
api/dangling-indices
2525
api/enrich-policies
2626
api/eql
27+
api/esql
2728
api/fleet
2829
api/graph-explore
2930
api/index-lifecycle-management

docs/sphinx/api/esql.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. _esql:
2+
3+
ES|QL
4+
-----
5+
.. py:module:: elasticsearch.client
6+
:noindex:
7+
8+
.. autoclass:: EsqlClient
9+
:members:

elasticsearch/_async/client/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from .dangling_indices import DanglingIndicesClient
5050
from .enrich import EnrichClient
5151
from .eql import EqlClient
52+
from .esql import EsqlClient
5253
from .features import FeaturesClient
5354
from .fleet import FleetClient
5455
from .graph import GraphClient
@@ -444,6 +445,7 @@ def __init__(
444445
self.dangling_indices = DanglingIndicesClient(self)
445446
self.enrich = EnrichClient(self)
446447
self.eql = EqlClient(self)
448+
self.esql = EsqlClient(self)
447449
self.graph = GraphClient(self)
448450
self.ilm = IlmClient(self)
449451
self.license = LicenseClient(self)

elasticsearch/_async/client/esql.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import typing as t
19+
20+
from elastic_transport import ObjectApiResponse
21+
22+
from ._base import NamespacedClient
23+
from .utils import _rewrite_parameters
24+
25+
26+
class EsqlClient(NamespacedClient):
27+
@_rewrite_parameters(
28+
body_fields=("query", "columnar", "filter", "locale", "params"),
29+
ignore_deprecated_options={"params"},
30+
)
31+
async def query(
32+
self,
33+
*,
34+
query: t.Optional[str] = None,
35+
columnar: t.Optional[bool] = None,
36+
delimiter: t.Optional[str] = None,
37+
error_trace: t.Optional[bool] = None,
38+
filter: t.Optional[t.Mapping[str, t.Any]] = None,
39+
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
40+
format: t.Optional[str] = None,
41+
human: t.Optional[bool] = None,
42+
locale: t.Optional[str] = None,
43+
params: t.Optional[t.Sequence[t.Union[None, bool, float, int, str]]] = None,
44+
pretty: t.Optional[bool] = None,
45+
body: t.Optional[t.Dict[str, t.Any]] = None,
46+
) -> ObjectApiResponse[t.Any]:
47+
"""
48+
Executes an ESQL request
49+
50+
`<https://www.elastic.co/guide/en/elasticsearch/reference/8.12/esql-rest.html>`_
51+
52+
:param query: The ES|QL query API accepts an ES|QL query string in the query
53+
parameter, runs it, and returns the results.
54+
:param columnar: By default, ES|QL returns results as rows. For example, FROM
55+
returns each individual document as one row. For the JSON, YAML, CBOR and
56+
smile formats, ES|QL can return the results in a columnar fashion where one
57+
row represents all the values of a certain column in the results.
58+
:param delimiter: The character to use between values within a CSV row. Only
59+
valid for the CSV format.
60+
:param filter: Specify a Query DSL query in the filter parameter to filter the
61+
set of documents that an ES|QL query runs on.
62+
:param format: A short version of the Accept header, e.g. json, yaml.
63+
:param locale:
64+
:param params: To avoid any attempts of hacking or code injection, extract the
65+
values in a separate list of parameters. Use question mark placeholders (?)
66+
in the query string for each of the parameters.
67+
"""
68+
if query is None and body is None:
69+
raise ValueError("Empty value passed for parameter 'query'")
70+
__path = "/_query"
71+
__query: t.Dict[str, t.Any] = {}
72+
__body: t.Dict[str, t.Any] = body if body is not None else {}
73+
if delimiter is not None:
74+
__query["delimiter"] = delimiter
75+
if error_trace is not None:
76+
__query["error_trace"] = error_trace
77+
if filter_path is not None:
78+
__query["filter_path"] = filter_path
79+
if format is not None:
80+
__query["format"] = format
81+
if human is not None:
82+
__query["human"] = human
83+
if pretty is not None:
84+
__query["pretty"] = pretty
85+
if not __body:
86+
if query is not None:
87+
__body["query"] = query
88+
if columnar is not None:
89+
__body["columnar"] = columnar
90+
if filter is not None:
91+
__body["filter"] = filter
92+
if locale is not None:
93+
__body["locale"] = locale
94+
if params is not None:
95+
__body["params"] = params
96+
__headers = {"accept": "application/json", "content-type": "application/json"}
97+
return await self.perform_request( # type: ignore[return-value]
98+
"POST", __path, params=__query, headers=__headers, body=__body
99+
)

elasticsearch/_sync/client/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
from .dangling_indices import DanglingIndicesClient
5050
from .enrich import EnrichClient
5151
from .eql import EqlClient
52+
from .esql import EsqlClient
5253
from .features import FeaturesClient
5354
from .fleet import FleetClient
5455
from .graph import GraphClient
@@ -444,6 +445,7 @@ def __init__(
444445
self.dangling_indices = DanglingIndicesClient(self)
445446
self.enrich = EnrichClient(self)
446447
self.eql = EqlClient(self)
448+
self.esql = EsqlClient(self)
447449
self.graph = GraphClient(self)
448450
self.ilm = IlmClient(self)
449451
self.license = LicenseClient(self)

elasticsearch/_sync/client/esql.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
import typing as t
19+
20+
from elastic_transport import ObjectApiResponse
21+
22+
from ._base import NamespacedClient
23+
from .utils import _rewrite_parameters
24+
25+
26+
class EsqlClient(NamespacedClient):
27+
@_rewrite_parameters(
28+
body_fields=("query", "columnar", "filter", "locale", "params"),
29+
ignore_deprecated_options={"params"},
30+
)
31+
def query(
32+
self,
33+
*,
34+
query: t.Optional[str] = None,
35+
columnar: t.Optional[bool] = None,
36+
delimiter: t.Optional[str] = None,
37+
error_trace: t.Optional[bool] = None,
38+
filter: t.Optional[t.Mapping[str, t.Any]] = None,
39+
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
40+
format: t.Optional[str] = None,
41+
human: t.Optional[bool] = None,
42+
locale: t.Optional[str] = None,
43+
params: t.Optional[t.Sequence[t.Union[None, bool, float, int, str]]] = None,
44+
pretty: t.Optional[bool] = None,
45+
body: t.Optional[t.Dict[str, t.Any]] = None,
46+
) -> ObjectApiResponse[t.Any]:
47+
"""
48+
Executes an ESQL request
49+
50+
`<https://www.elastic.co/guide/en/elasticsearch/reference/8.12/esql-rest.html>`_
51+
52+
:param query: The ES|QL query API accepts an ES|QL query string in the query
53+
parameter, runs it, and returns the results.
54+
:param columnar: By default, ES|QL returns results as rows. For example, FROM
55+
returns each individual document as one row. For the JSON, YAML, CBOR and
56+
smile formats, ES|QL can return the results in a columnar fashion where one
57+
row represents all the values of a certain column in the results.
58+
:param delimiter: The character to use between values within a CSV row. Only
59+
valid for the CSV format.
60+
:param filter: Specify a Query DSL query in the filter parameter to filter the
61+
set of documents that an ES|QL query runs on.
62+
:param format: A short version of the Accept header, e.g. json, yaml.
63+
:param locale:
64+
:param params: To avoid any attempts of hacking or code injection, extract the
65+
values in a separate list of parameters. Use question mark placeholders (?)
66+
in the query string for each of the parameters.
67+
"""
68+
if query is None and body is None:
69+
raise ValueError("Empty value passed for parameter 'query'")
70+
__path = "/_query"
71+
__query: t.Dict[str, t.Any] = {}
72+
__body: t.Dict[str, t.Any] = body if body is not None else {}
73+
if delimiter is not None:
74+
__query["delimiter"] = delimiter
75+
if error_trace is not None:
76+
__query["error_trace"] = error_trace
77+
if filter_path is not None:
78+
__query["filter_path"] = filter_path
79+
if format is not None:
80+
__query["format"] = format
81+
if human is not None:
82+
__query["human"] = human
83+
if pretty is not None:
84+
__query["pretty"] = pretty
85+
if not __body:
86+
if query is not None:
87+
__body["query"] = query
88+
if columnar is not None:
89+
__body["columnar"] = columnar
90+
if filter is not None:
91+
__body["filter"] = filter
92+
if locale is not None:
93+
__body["locale"] = locale
94+
if params is not None:
95+
__body["params"] = params
96+
__headers = {"accept": "application/json", "content-type": "application/json"}
97+
return self.perform_request( # type: ignore[return-value]
98+
"POST", __path, params=__query, headers=__headers, body=__body
99+
)

elasticsearch/client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
)
3333
from ._sync.client.enrich import EnrichClient as EnrichClient # noqa: F401
3434
from ._sync.client.eql import EqlClient as EqlClient # noqa: F401
35+
from ._sync.client.esql import EsqlClient as EsqlClient # noqa: F401
3536
from ._sync.client.features import FeaturesClient as FeaturesClient # noqa: F401
3637
from ._sync.client.fleet import FleetClient as FleetClient # noqa: F401
3738
from ._sync.client.graph import GraphClient as GraphClient # noqa: F401

0 commit comments

Comments
 (0)