elasticsearch 9.0.2__py3-none-any.whl → 9.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- elasticsearch/_async/client/__init__.py +42 -198
- elasticsearch/_async/client/cat.py +393 -25
- elasticsearch/_async/client/cluster.py +14 -4
- elasticsearch/_async/client/eql.py +10 -2
- elasticsearch/_async/client/esql.py +17 -4
- elasticsearch/_async/client/indices.py +87 -43
- elasticsearch/_async/client/inference.py +108 -3
- elasticsearch/_async/client/ingest.py +0 -7
- elasticsearch/_async/client/license.py +4 -4
- elasticsearch/_async/client/ml.py +6 -17
- elasticsearch/_async/client/monitoring.py +1 -1
- elasticsearch/_async/client/rollup.py +1 -22
- elasticsearch/_async/client/security.py +11 -17
- elasticsearch/_async/client/snapshot.py +6 -0
- elasticsearch/_async/client/synonyms.py +1 -0
- elasticsearch/_async/client/watcher.py +4 -2
- elasticsearch/_sync/client/__init__.py +42 -198
- elasticsearch/_sync/client/cat.py +393 -25
- elasticsearch/_sync/client/cluster.py +14 -4
- elasticsearch/_sync/client/eql.py +10 -2
- elasticsearch/_sync/client/esql.py +17 -4
- elasticsearch/_sync/client/indices.py +87 -43
- elasticsearch/_sync/client/inference.py +108 -3
- elasticsearch/_sync/client/ingest.py +0 -7
- elasticsearch/_sync/client/license.py +4 -4
- elasticsearch/_sync/client/ml.py +6 -17
- elasticsearch/_sync/client/monitoring.py +1 -1
- elasticsearch/_sync/client/rollup.py +1 -22
- elasticsearch/_sync/client/security.py +11 -17
- elasticsearch/_sync/client/snapshot.py +6 -0
- elasticsearch/_sync/client/synonyms.py +1 -0
- elasticsearch/_sync/client/watcher.py +4 -2
- elasticsearch/_version.py +1 -1
- elasticsearch/compat.py +5 -0
- elasticsearch/dsl/__init__.py +2 -1
- elasticsearch/dsl/document_base.py +176 -16
- elasticsearch/dsl/field.py +222 -47
- elasticsearch/dsl/query.py +7 -4
- elasticsearch/dsl/types.py +105 -80
- elasticsearch/dsl/utils.py +1 -1
- elasticsearch/{dsl/_sync/_sync_check → esql}/__init__.py +2 -0
- elasticsearch/esql/esql.py +1105 -0
- elasticsearch/esql/functions.py +1738 -0
- {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/METADATA +1 -1
- {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/RECORD +48 -52
- elasticsearch/dsl/_sync/_sync_check/document.py +0 -514
- elasticsearch/dsl/_sync/_sync_check/faceted_search.py +0 -50
- elasticsearch/dsl/_sync/_sync_check/index.py +0 -597
- elasticsearch/dsl/_sync/_sync_check/mapping.py +0 -49
- elasticsearch/dsl/_sync/_sync_check/search.py +0 -230
- elasticsearch/dsl/_sync/_sync_check/update_by_query.py +0 -45
- {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/WHEEL +0 -0
- {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/licenses/LICENSE +0 -0
- {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/licenses/NOTICE +0 -0
|
@@ -2213,13 +2213,10 @@ class SecurityClient(NamespacedClient):
|
|
|
2213
2213
|
def get_user_privileges(
|
|
2214
2214
|
self,
|
|
2215
2215
|
*,
|
|
2216
|
-
application: t.Optional[str] = None,
|
|
2217
2216
|
error_trace: t.Optional[bool] = None,
|
|
2218
2217
|
filter_path: t.Optional[t.Union[str, t.Sequence[str]]] = None,
|
|
2219
2218
|
human: t.Optional[bool] = None,
|
|
2220
2219
|
pretty: t.Optional[bool] = None,
|
|
2221
|
-
priviledge: t.Optional[str] = None,
|
|
2222
|
-
username: t.Optional[t.Union[None, str]] = None,
|
|
2223
2220
|
) -> ObjectApiResponse[t.Any]:
|
|
2224
2221
|
"""
|
|
2225
2222
|
.. raw:: html
|
|
@@ -2232,19 +2229,10 @@ class SecurityClient(NamespacedClient):
|
|
|
2232
2229
|
|
|
2233
2230
|
|
|
2234
2231
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-security-get-user-privileges>`_
|
|
2235
|
-
|
|
2236
|
-
:param application: The name of the application. Application privileges are always
|
|
2237
|
-
associated with exactly one application. If you do not specify this parameter,
|
|
2238
|
-
the API returns information about all privileges for all applications.
|
|
2239
|
-
:param priviledge: The name of the privilege. If you do not specify this parameter,
|
|
2240
|
-
the API returns information about all privileges for the requested application.
|
|
2241
|
-
:param username:
|
|
2242
2232
|
"""
|
|
2243
2233
|
__path_parts: t.Dict[str, str] = {}
|
|
2244
2234
|
__path = "/_security/user/_privileges"
|
|
2245
2235
|
__query: t.Dict[str, t.Any] = {}
|
|
2246
|
-
if application is not None:
|
|
2247
|
-
__query["application"] = application
|
|
2248
2236
|
if error_trace is not None:
|
|
2249
2237
|
__query["error_trace"] = error_trace
|
|
2250
2238
|
if filter_path is not None:
|
|
@@ -2253,10 +2241,6 @@ class SecurityClient(NamespacedClient):
|
|
|
2253
2241
|
__query["human"] = human
|
|
2254
2242
|
if pretty is not None:
|
|
2255
2243
|
__query["pretty"] = pretty
|
|
2256
|
-
if priviledge is not None:
|
|
2257
|
-
__query["priviledge"] = priviledge
|
|
2258
|
-
if username is not None:
|
|
2259
|
-
__query["username"] = username
|
|
2260
2244
|
__headers = {"accept": "application/json"}
|
|
2261
2245
|
return self.perform_request( # type: ignore[return-value]
|
|
2262
2246
|
"GET",
|
|
@@ -2345,6 +2329,9 @@ class SecurityClient(NamespacedClient):
|
|
|
2345
2329
|
human: t.Optional[bool] = None,
|
|
2346
2330
|
password: t.Optional[str] = None,
|
|
2347
2331
|
pretty: t.Optional[bool] = None,
|
|
2332
|
+
refresh: t.Optional[
|
|
2333
|
+
t.Union[bool, str, t.Literal["false", "true", "wait_for"]]
|
|
2334
|
+
] = None,
|
|
2348
2335
|
run_as: t.Optional[str] = None,
|
|
2349
2336
|
username: t.Optional[str] = None,
|
|
2350
2337
|
body: t.Optional[t.Dict[str, t.Any]] = None,
|
|
@@ -2382,6 +2369,9 @@ class SecurityClient(NamespacedClient):
|
|
|
2382
2369
|
types.
|
|
2383
2370
|
:param password: The user's password. If you specify the `password` grant type,
|
|
2384
2371
|
this parameter is required. It is not valid with other grant types.
|
|
2372
|
+
:param refresh: If 'true', Elasticsearch refreshes the affected shards to make
|
|
2373
|
+
this operation visible to search. If 'wait_for', it waits for a refresh to
|
|
2374
|
+
make this operation visible to search. If 'false', nothing is done with refreshes.
|
|
2385
2375
|
:param run_as: The name of the user to be impersonated.
|
|
2386
2376
|
:param username: The user name that identifies the user. If you specify the `password`
|
|
2387
2377
|
grant type, this parameter is required. It is not valid with other grant
|
|
@@ -2403,6 +2393,8 @@ class SecurityClient(NamespacedClient):
|
|
|
2403
2393
|
__query["human"] = human
|
|
2404
2394
|
if pretty is not None:
|
|
2405
2395
|
__query["pretty"] = pretty
|
|
2396
|
+
if refresh is not None:
|
|
2397
|
+
__query["refresh"] = refresh
|
|
2406
2398
|
if not __body:
|
|
2407
2399
|
if api_key is not None:
|
|
2408
2400
|
__body["api_key"] = api_key
|
|
@@ -3553,7 +3545,8 @@ class SecurityClient(NamespacedClient):
|
|
|
3553
3545
|
You can optionally filter the results with a query.</p>
|
|
3554
3546
|
<p>To use this API, you must have at least the <code>manage_own_api_key</code> or the <code>read_security</code> cluster privileges.
|
|
3555
3547
|
If you have only the <code>manage_own_api_key</code> privilege, this API returns only the API keys that you own.
|
|
3556
|
-
If you have the <code>read_security</code>, <code>manage_api_key</code>, or greater privileges (including <code>manage_security</code>), this API returns all API keys regardless of ownership
|
|
3548
|
+
If you have the <code>read_security</code>, <code>manage_api_key</code>, or greater privileges (including <code>manage_security</code>), this API returns all API keys regardless of ownership.
|
|
3549
|
+
Refer to the linked documentation for examples of how to find API keys:</p>
|
|
3557
3550
|
|
|
3558
3551
|
|
|
3559
3552
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-security-query-api-keys>`_
|
|
@@ -4466,6 +4459,7 @@ class SecurityClient(NamespacedClient):
|
|
|
4466
4459
|
<p>This API supports updates to an API key's access scope, metadata, and expiration.
|
|
4467
4460
|
The owner user's information, such as the <code>username</code> and <code>realm</code>, is also updated automatically on every call.</p>
|
|
4468
4461
|
<p>NOTE: This API cannot update REST API keys, which should be updated by either the update API key or bulk update API keys API.</p>
|
|
4462
|
+
<p>To learn more about how to use this API, refer to the <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/update-cc-api-key-examples">Update cross cluter API key API examples page</a>.</p>
|
|
4469
4463
|
|
|
4470
4464
|
|
|
4471
4465
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-security-update-cross-cluster-api-key>`_
|
|
@@ -403,6 +403,7 @@ class SnapshotClient(NamespacedClient):
|
|
|
403
403
|
human: t.Optional[bool] = None,
|
|
404
404
|
master_timeout: t.Optional[t.Union[str, t.Literal[-1], t.Literal[0]]] = None,
|
|
405
405
|
pretty: t.Optional[bool] = None,
|
|
406
|
+
wait_for_completion: t.Optional[bool] = None,
|
|
406
407
|
) -> ObjectApiResponse[t.Any]:
|
|
407
408
|
"""
|
|
408
409
|
.. raw:: html
|
|
@@ -418,6 +419,9 @@ class SnapshotClient(NamespacedClient):
|
|
|
418
419
|
:param master_timeout: The period to wait for the master node. If the master
|
|
419
420
|
node is not available before the timeout expires, the request fails and returns
|
|
420
421
|
an error. To indicate that the request should never timeout, set it to `-1`.
|
|
422
|
+
:param wait_for_completion: If `true`, the request returns a response when the
|
|
423
|
+
matching snapshots are all deleted. If `false`, the request returns a response
|
|
424
|
+
as soon as the deletes are scheduled.
|
|
421
425
|
"""
|
|
422
426
|
if repository in SKIP_IN_PATH:
|
|
423
427
|
raise ValueError("Empty value passed for parameter 'repository'")
|
|
@@ -439,6 +443,8 @@ class SnapshotClient(NamespacedClient):
|
|
|
439
443
|
__query["master_timeout"] = master_timeout
|
|
440
444
|
if pretty is not None:
|
|
441
445
|
__query["pretty"] = pretty
|
|
446
|
+
if wait_for_completion is not None:
|
|
447
|
+
__query["wait_for_completion"] = wait_for_completion
|
|
442
448
|
__headers = {"accept": "application/json"}
|
|
443
449
|
return self.perform_request( # type: ignore[return-value]
|
|
444
450
|
"DELETE",
|
|
@@ -309,6 +309,7 @@ class SynonymsClient(NamespacedClient):
|
|
|
309
309
|
If you need to manage more synonym rules, you can create multiple synonym sets.</p>
|
|
310
310
|
<p>When an existing synonyms set is updated, the search analyzers that use the synonyms set are reloaded automatically for all indices.
|
|
311
311
|
This is equivalent to invoking the reload search analyzers API for all indices that use the synonyms set.</p>
|
|
312
|
+
<p>For practical examples of how to create or update a synonyms set, refer to the External documentation.</p>
|
|
312
313
|
|
|
313
314
|
|
|
314
315
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-synonyms-put-synonym>`_
|
|
@@ -45,7 +45,8 @@ class WatcherClient(NamespacedClient):
|
|
|
45
45
|
<p>IMPORTANT: If the specified watch is currently being executed, this API will return an error
|
|
46
46
|
The reason for this behavior is to prevent overwriting the watch status from a watch execution.</p>
|
|
47
47
|
<p>Acknowledging an action throttles further executions of that action until its <code>ack.state</code> is reset to <code>awaits_successful_execution</code>.
|
|
48
|
-
This happens when the condition of the watch is not met (the condition evaluates to false)
|
|
48
|
+
This happens when the condition of the watch is not met (the condition evaluates to false).
|
|
49
|
+
To demonstrate how throttling works in practice and how it can be configured for individual actions within a watch, refer to External documentation.</p>
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-watcher-ack-watch>`_
|
|
@@ -274,7 +275,8 @@ class WatcherClient(NamespacedClient):
|
|
|
274
275
|
This serves as great tool for testing and debugging your watches prior to adding them to Watcher.</p>
|
|
275
276
|
<p>When Elasticsearch security features are enabled on your cluster, watches are run with the privileges of the user that stored the watches.
|
|
276
277
|
If your user is allowed to read index <code>a</code>, but not index <code>b</code>, then the exact same set of rules will apply during execution of a watch.</p>
|
|
277
|
-
<p>When using the run watch API, the authorization data of the user that called the API will be used as a base, instead of the information who stored the watch
|
|
278
|
+
<p>When using the run watch API, the authorization data of the user that called the API will be used as a base, instead of the information who stored the watch.
|
|
279
|
+
Refer to the external documentation for examples of watch execution requests, including existing, customized, and inline watches.</p>
|
|
278
280
|
|
|
279
281
|
|
|
280
282
|
`<https://www.elastic.co/docs/api/doc/elasticsearch/v9/operation/operation-watcher-execute-watch>`_
|
elasticsearch/_version.py
CHANGED
elasticsearch/compat.py
CHANGED
|
@@ -16,12 +16,15 @@
|
|
|
16
16
|
# under the License.
|
|
17
17
|
|
|
18
18
|
import inspect
|
|
19
|
+
import os
|
|
19
20
|
import sys
|
|
20
21
|
from pathlib import Path
|
|
21
22
|
from typing import Tuple, Type, Union
|
|
22
23
|
|
|
23
24
|
string_types: Tuple[Type[str], Type[bytes]] = (str, bytes)
|
|
24
25
|
|
|
26
|
+
DISABLE_WARN_STACKLEVEL_ENV_VAR = "DISABLE_WARN_STACKLEVEL"
|
|
27
|
+
|
|
25
28
|
|
|
26
29
|
def to_str(x: Union[str, bytes], encoding: str = "ascii") -> str:
|
|
27
30
|
if not isinstance(x, str):
|
|
@@ -37,6 +40,8 @@ def to_bytes(x: Union[str, bytes], encoding: str = "ascii") -> bytes:
|
|
|
37
40
|
|
|
38
41
|
def warn_stacklevel() -> int:
|
|
39
42
|
"""Dynamically determine warning stacklevel for warnings based on the call stack"""
|
|
43
|
+
if os.environ.get(DISABLE_WARN_STACKLEVEL_ENV_VAR) in ["1", "true", "True"]:
|
|
44
|
+
return 0
|
|
40
45
|
try:
|
|
41
46
|
# Grab the root module from the current module '__name__'
|
|
42
47
|
module_name = __name__.partition(".")[0]
|
elasticsearch/dsl/__init__.py
CHANGED
|
@@ -19,7 +19,7 @@ from . import async_connections, connections
|
|
|
19
19
|
from .aggs import A, Agg
|
|
20
20
|
from .analysis import analyzer, char_filter, normalizer, token_filter, tokenizer
|
|
21
21
|
from .document import AsyncDocument, Document
|
|
22
|
-
from .document_base import InnerDoc, M, MetaField, mapped_field
|
|
22
|
+
from .document_base import E, InnerDoc, M, MetaField, mapped_field
|
|
23
23
|
from .exceptions import (
|
|
24
24
|
ElasticsearchDslException,
|
|
25
25
|
IllegalOperation,
|
|
@@ -135,6 +135,7 @@ __all__ = [
|
|
|
135
135
|
"Double",
|
|
136
136
|
"DoubleRange",
|
|
137
137
|
"DslBase",
|
|
138
|
+
"E",
|
|
138
139
|
"ElasticsearchDslException",
|
|
139
140
|
"EmptySearch",
|
|
140
141
|
"Facet",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# specific language governing permissions and limitations
|
|
16
16
|
# under the License.
|
|
17
17
|
|
|
18
|
+
import json
|
|
18
19
|
from datetime import date, datetime
|
|
19
20
|
from fnmatch import fnmatch
|
|
20
21
|
from typing import (
|
|
@@ -56,7 +57,163 @@ class MetaField:
|
|
|
56
57
|
self.args, self.kwargs = args, kwargs
|
|
57
58
|
|
|
58
59
|
|
|
59
|
-
class
|
|
60
|
+
class InstrumentedExpression:
|
|
61
|
+
"""Proxy object for a ES|QL expression."""
|
|
62
|
+
|
|
63
|
+
def __init__(self, expr: str):
|
|
64
|
+
self._expr = expr
|
|
65
|
+
|
|
66
|
+
def _render_value(self, value: Any) -> str:
|
|
67
|
+
if isinstance(value, InstrumentedExpression):
|
|
68
|
+
return str(value)
|
|
69
|
+
return json.dumps(value)
|
|
70
|
+
|
|
71
|
+
def __str__(self) -> str:
|
|
72
|
+
return self._expr
|
|
73
|
+
|
|
74
|
+
def __repr__(self) -> str:
|
|
75
|
+
return f"InstrumentedExpression[{self._expr}]"
|
|
76
|
+
|
|
77
|
+
def __pos__(self) -> "InstrumentedExpression":
|
|
78
|
+
return self
|
|
79
|
+
|
|
80
|
+
def __neg__(self) -> "InstrumentedExpression":
|
|
81
|
+
return InstrumentedExpression(f"-({self._expr})")
|
|
82
|
+
|
|
83
|
+
def __eq__(self, value: Any) -> "InstrumentedExpression": # type: ignore[override]
|
|
84
|
+
return InstrumentedExpression(f"{self._expr} == {self._render_value(value)}")
|
|
85
|
+
|
|
86
|
+
def __ne__(self, value: Any) -> "InstrumentedExpression": # type: ignore[override]
|
|
87
|
+
return InstrumentedExpression(f"{self._expr} != {self._render_value(value)}")
|
|
88
|
+
|
|
89
|
+
def __lt__(self, value: Any) -> "InstrumentedExpression":
|
|
90
|
+
return InstrumentedExpression(f"{self._expr} < {self._render_value(value)}")
|
|
91
|
+
|
|
92
|
+
def __gt__(self, value: Any) -> "InstrumentedExpression":
|
|
93
|
+
return InstrumentedExpression(f"{self._expr} > {self._render_value(value)}")
|
|
94
|
+
|
|
95
|
+
def __le__(self, value: Any) -> "InstrumentedExpression":
|
|
96
|
+
return InstrumentedExpression(f"{self._expr} <= {self._render_value(value)}")
|
|
97
|
+
|
|
98
|
+
def __ge__(self, value: Any) -> "InstrumentedExpression":
|
|
99
|
+
return InstrumentedExpression(f"{self._expr} >= {self._render_value(value)}")
|
|
100
|
+
|
|
101
|
+
def __add__(self, value: Any) -> "InstrumentedExpression":
|
|
102
|
+
return InstrumentedExpression(f"{self._expr} + {self._render_value(value)}")
|
|
103
|
+
|
|
104
|
+
def __radd__(self, value: Any) -> "InstrumentedExpression":
|
|
105
|
+
return InstrumentedExpression(f"{self._render_value(value)} + {self._expr}")
|
|
106
|
+
|
|
107
|
+
def __sub__(self, value: Any) -> "InstrumentedExpression":
|
|
108
|
+
return InstrumentedExpression(f"{self._expr} - {self._render_value(value)}")
|
|
109
|
+
|
|
110
|
+
def __rsub__(self, value: Any) -> "InstrumentedExpression":
|
|
111
|
+
return InstrumentedExpression(f"{self._render_value(value)} - {self._expr}")
|
|
112
|
+
|
|
113
|
+
def __mul__(self, value: Any) -> "InstrumentedExpression":
|
|
114
|
+
return InstrumentedExpression(f"{self._expr} * {self._render_value(value)}")
|
|
115
|
+
|
|
116
|
+
def __rmul__(self, value: Any) -> "InstrumentedExpression":
|
|
117
|
+
return InstrumentedExpression(f"{self._render_value(value)} * {self._expr}")
|
|
118
|
+
|
|
119
|
+
def __truediv__(self, value: Any) -> "InstrumentedExpression":
|
|
120
|
+
return InstrumentedExpression(f"{self._expr} / {self._render_value(value)}")
|
|
121
|
+
|
|
122
|
+
def __rtruediv__(self, value: Any) -> "InstrumentedExpression":
|
|
123
|
+
return InstrumentedExpression(f"{self._render_value(value)} / {self._expr}")
|
|
124
|
+
|
|
125
|
+
def __mod__(self, value: Any) -> "InstrumentedExpression":
|
|
126
|
+
return InstrumentedExpression(f"{self._expr} % {self._render_value(value)}")
|
|
127
|
+
|
|
128
|
+
def __rmod__(self, value: Any) -> "InstrumentedExpression":
|
|
129
|
+
return InstrumentedExpression(f"{self._render_value(value)} % {self._expr}")
|
|
130
|
+
|
|
131
|
+
def is_null(self) -> "InstrumentedExpression":
|
|
132
|
+
"""Compare the expression against NULL."""
|
|
133
|
+
return InstrumentedExpression(f"{self._expr} IS NULL")
|
|
134
|
+
|
|
135
|
+
def is_not_null(self) -> "InstrumentedExpression":
|
|
136
|
+
"""Compare the expression against NOT NULL."""
|
|
137
|
+
return InstrumentedExpression(f"{self._expr} IS NOT NULL")
|
|
138
|
+
|
|
139
|
+
def in_(self, *values: Any) -> "InstrumentedExpression":
|
|
140
|
+
"""Test if the expression equals one of the given values."""
|
|
141
|
+
rendered_values = ", ".join([f"{value}" for value in values])
|
|
142
|
+
return InstrumentedExpression(f"{self._expr} IN ({rendered_values})")
|
|
143
|
+
|
|
144
|
+
def like(self, *patterns: str) -> "InstrumentedExpression":
|
|
145
|
+
"""Filter the expression using a string pattern."""
|
|
146
|
+
if len(patterns) == 1:
|
|
147
|
+
return InstrumentedExpression(
|
|
148
|
+
f"{self._expr} LIKE {self._render_value(patterns[0])}"
|
|
149
|
+
)
|
|
150
|
+
else:
|
|
151
|
+
return InstrumentedExpression(
|
|
152
|
+
f'{self._expr} LIKE ({", ".join([self._render_value(p) for p in patterns])})'
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def rlike(self, *patterns: str) -> "InstrumentedExpression":
|
|
156
|
+
"""Filter the expression using a regular expression."""
|
|
157
|
+
if len(patterns) == 1:
|
|
158
|
+
return InstrumentedExpression(
|
|
159
|
+
f"{self._expr} RLIKE {self._render_value(patterns[0])}"
|
|
160
|
+
)
|
|
161
|
+
else:
|
|
162
|
+
return InstrumentedExpression(
|
|
163
|
+
f'{self._expr} RLIKE ({", ".join([self._render_value(p) for p in patterns])})'
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def match(self, query: str) -> "InstrumentedExpression":
|
|
167
|
+
"""Perform a match query on the field."""
|
|
168
|
+
return InstrumentedExpression(f"{self._expr}:{self._render_value(query)}")
|
|
169
|
+
|
|
170
|
+
def asc(self) -> "InstrumentedExpression":
|
|
171
|
+
"""Return the field name representation for ascending sort order.
|
|
172
|
+
|
|
173
|
+
For use in ES|QL queries only.
|
|
174
|
+
"""
|
|
175
|
+
return InstrumentedExpression(f"{self._expr} ASC")
|
|
176
|
+
|
|
177
|
+
def desc(self) -> "InstrumentedExpression":
|
|
178
|
+
"""Return the field name representation for descending sort order.
|
|
179
|
+
|
|
180
|
+
For use in ES|QL queries only.
|
|
181
|
+
"""
|
|
182
|
+
return InstrumentedExpression(f"{self._expr} DESC")
|
|
183
|
+
|
|
184
|
+
def nulls_first(self) -> "InstrumentedExpression":
|
|
185
|
+
"""Return the field name representation for nulls first sort order.
|
|
186
|
+
|
|
187
|
+
For use in ES|QL queries only.
|
|
188
|
+
"""
|
|
189
|
+
return InstrumentedExpression(f"{self._expr} NULLS FIRST")
|
|
190
|
+
|
|
191
|
+
def nulls_last(self) -> "InstrumentedExpression":
|
|
192
|
+
"""Return the field name representation for nulls last sort order.
|
|
193
|
+
|
|
194
|
+
For use in ES|QL queries only.
|
|
195
|
+
"""
|
|
196
|
+
return InstrumentedExpression(f"{self._expr} NULLS LAST")
|
|
197
|
+
|
|
198
|
+
def where(
|
|
199
|
+
self, *expressions: Union[str, "InstrumentedExpression"]
|
|
200
|
+
) -> "InstrumentedExpression":
|
|
201
|
+
"""Add a condition to be met for the row to be included.
|
|
202
|
+
|
|
203
|
+
Use only in expressions given in the ``STATS`` command.
|
|
204
|
+
"""
|
|
205
|
+
if len(expressions) == 1:
|
|
206
|
+
return InstrumentedExpression(f"{self._expr} WHERE {expressions[0]}")
|
|
207
|
+
else:
|
|
208
|
+
return InstrumentedExpression(
|
|
209
|
+
f'{self._expr} WHERE {" AND ".join([f"({expr})" for expr in expressions])}'
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
E = InstrumentedExpression
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class InstrumentedField(InstrumentedExpression):
|
|
60
217
|
"""Proxy object for a mapped document field.
|
|
61
218
|
|
|
62
219
|
An object of this instance is returned when a field is accessed as a class
|
|
@@ -71,8 +228,8 @@ class InstrumentedField:
|
|
|
71
228
|
s = s.sort(-MyDocument.name) # sort by name in descending order
|
|
72
229
|
"""
|
|
73
230
|
|
|
74
|
-
def __init__(self, name: str, field: Field):
|
|
75
|
-
|
|
231
|
+
def __init__(self, name: str, field: Optional[Field]):
|
|
232
|
+
super().__init__(name)
|
|
76
233
|
self._field = field
|
|
77
234
|
|
|
78
235
|
# note that the return value type here assumes classes will only be used to
|
|
@@ -83,26 +240,29 @@ class InstrumentedField:
|
|
|
83
240
|
# first let's see if this is an attribute of this object
|
|
84
241
|
return super().__getattribute__(attr) # type: ignore[no-any-return]
|
|
85
242
|
except AttributeError:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
243
|
+
if self._field:
|
|
244
|
+
try:
|
|
245
|
+
# next we see if we have a sub-field with this name
|
|
246
|
+
return InstrumentedField(f"{self._expr}.{attr}", self._field[attr])
|
|
247
|
+
except KeyError:
|
|
248
|
+
# lastly we let the wrapped field resolve this attribute
|
|
249
|
+
return getattr(self._field, attr) # type: ignore[no-any-return]
|
|
250
|
+
else:
|
|
251
|
+
raise
|
|
252
|
+
|
|
253
|
+
def __pos__(self) -> str: # type: ignore[override]
|
|
94
254
|
"""Return the field name representation for ascending sort order"""
|
|
95
|
-
return f"{self.
|
|
255
|
+
return f"{self._expr}"
|
|
96
256
|
|
|
97
|
-
def __neg__(self) -> str:
|
|
257
|
+
def __neg__(self) -> str: # type: ignore[override]
|
|
98
258
|
"""Return the field name representation for descending sort order"""
|
|
99
|
-
return f"-{self.
|
|
259
|
+
return f"-{self._expr}"
|
|
100
260
|
|
|
101
261
|
def __str__(self) -> str:
|
|
102
|
-
return self.
|
|
262
|
+
return self._expr
|
|
103
263
|
|
|
104
264
|
def __repr__(self) -> str:
|
|
105
|
-
return f"InstrumentedField[{self.
|
|
265
|
+
return f"InstrumentedField[{self._expr}]"
|
|
106
266
|
|
|
107
267
|
|
|
108
268
|
class DocumentMeta(type):
|