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.
Files changed (54) hide show
  1. elasticsearch/_async/client/__init__.py +42 -198
  2. elasticsearch/_async/client/cat.py +393 -25
  3. elasticsearch/_async/client/cluster.py +14 -4
  4. elasticsearch/_async/client/eql.py +10 -2
  5. elasticsearch/_async/client/esql.py +17 -4
  6. elasticsearch/_async/client/indices.py +87 -43
  7. elasticsearch/_async/client/inference.py +108 -3
  8. elasticsearch/_async/client/ingest.py +0 -7
  9. elasticsearch/_async/client/license.py +4 -4
  10. elasticsearch/_async/client/ml.py +6 -17
  11. elasticsearch/_async/client/monitoring.py +1 -1
  12. elasticsearch/_async/client/rollup.py +1 -22
  13. elasticsearch/_async/client/security.py +11 -17
  14. elasticsearch/_async/client/snapshot.py +6 -0
  15. elasticsearch/_async/client/synonyms.py +1 -0
  16. elasticsearch/_async/client/watcher.py +4 -2
  17. elasticsearch/_sync/client/__init__.py +42 -198
  18. elasticsearch/_sync/client/cat.py +393 -25
  19. elasticsearch/_sync/client/cluster.py +14 -4
  20. elasticsearch/_sync/client/eql.py +10 -2
  21. elasticsearch/_sync/client/esql.py +17 -4
  22. elasticsearch/_sync/client/indices.py +87 -43
  23. elasticsearch/_sync/client/inference.py +108 -3
  24. elasticsearch/_sync/client/ingest.py +0 -7
  25. elasticsearch/_sync/client/license.py +4 -4
  26. elasticsearch/_sync/client/ml.py +6 -17
  27. elasticsearch/_sync/client/monitoring.py +1 -1
  28. elasticsearch/_sync/client/rollup.py +1 -22
  29. elasticsearch/_sync/client/security.py +11 -17
  30. elasticsearch/_sync/client/snapshot.py +6 -0
  31. elasticsearch/_sync/client/synonyms.py +1 -0
  32. elasticsearch/_sync/client/watcher.py +4 -2
  33. elasticsearch/_version.py +1 -1
  34. elasticsearch/compat.py +5 -0
  35. elasticsearch/dsl/__init__.py +2 -1
  36. elasticsearch/dsl/document_base.py +176 -16
  37. elasticsearch/dsl/field.py +222 -47
  38. elasticsearch/dsl/query.py +7 -4
  39. elasticsearch/dsl/types.py +105 -80
  40. elasticsearch/dsl/utils.py +1 -1
  41. elasticsearch/{dsl/_sync/_sync_check → esql}/__init__.py +2 -0
  42. elasticsearch/esql/esql.py +1105 -0
  43. elasticsearch/esql/functions.py +1738 -0
  44. {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/METADATA +1 -1
  45. {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/RECORD +48 -52
  46. elasticsearch/dsl/_sync/_sync_check/document.py +0 -514
  47. elasticsearch/dsl/_sync/_sync_check/faceted_search.py +0 -50
  48. elasticsearch/dsl/_sync/_sync_check/index.py +0 -597
  49. elasticsearch/dsl/_sync/_sync_check/mapping.py +0 -49
  50. elasticsearch/dsl/_sync/_sync_check/search.py +0 -230
  51. elasticsearch/dsl/_sync/_sync_check/update_by_query.py +0 -45
  52. {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/WHEEL +0 -0
  53. {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/licenses/LICENSE +0 -0
  54. {elasticsearch-9.0.2.dist-info → elasticsearch-9.0.3.dist-info}/licenses/NOTICE +0 -0
@@ -1,514 +0,0 @@
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 collections.abc
19
- from typing import (
20
- TYPE_CHECKING,
21
- Any,
22
- Dict,
23
- Iterable,
24
- List,
25
- Optional,
26
- Tuple,
27
- Union,
28
- cast,
29
- )
30
-
31
- from typing_extensions import Self, dataclass_transform
32
-
33
- from elasticsearch.exceptions import NotFoundError, RequestError
34
- from elasticsearch.helpers import bulk
35
-
36
- from .._sync.index import Index
37
- from ..connections import get_connection
38
- from ..document_base import DocumentBase, DocumentMeta, mapped_field
39
- from ..exceptions import IllegalOperation
40
- from ..utils import DOC_META_FIELDS, META_FIELDS, UsingType, merge
41
- from .search import Search
42
-
43
- if TYPE_CHECKING:
44
- from elasticsearch import Elasticsearch
45
-
46
-
47
- class IndexMeta(DocumentMeta):
48
- _index: Index
49
-
50
- # global flag to guard us from associating an Index with the base Document
51
- # class, only user defined subclasses should have an _index attr
52
- _document_initialized = False
53
-
54
- def __new__(
55
- cls, name: str, bases: Tuple[type, ...], attrs: Dict[str, Any]
56
- ) -> "IndexMeta":
57
- new_cls = super().__new__(cls, name, bases, attrs)
58
- if cls._document_initialized:
59
- index_opts = attrs.pop("Index", None)
60
- index = cls.construct_index(index_opts, bases)
61
- new_cls._index = index
62
- index.document(new_cls)
63
- cls._document_initialized = True
64
- return cast(IndexMeta, new_cls)
65
-
66
- @classmethod
67
- def construct_index(cls, opts: Dict[str, Any], bases: Tuple[type, ...]) -> Index:
68
- if opts is None:
69
- for b in bases:
70
- if hasattr(b, "_index"):
71
- return b._index
72
-
73
- # Set None as Index name so it will set _all while making the query
74
- return Index(name=None)
75
-
76
- i = Index(getattr(opts, "name", "*"), using=getattr(opts, "using", "default"))
77
- i.settings(**getattr(opts, "settings", {}))
78
- i.aliases(**getattr(opts, "aliases", {}))
79
- for a in getattr(opts, "analyzers", ()):
80
- i.analyzer(a)
81
- return i
82
-
83
-
84
- @dataclass_transform(field_specifiers=(mapped_field,))
85
- class Document(DocumentBase, metaclass=IndexMeta):
86
- """
87
- Model-like class for persisting documents in elasticsearch.
88
- """
89
-
90
- if TYPE_CHECKING:
91
- _index: Index
92
-
93
- @classmethod
94
- def _get_using(cls, using: Optional[UsingType] = None) -> UsingType:
95
- return using or cls._index._using
96
-
97
- @classmethod
98
- def _get_connection(cls, using: Optional[UsingType] = None) -> "Elasticsearch":
99
- return get_connection(cls._get_using(using))
100
-
101
- @classmethod
102
- def init(
103
- cls, index: Optional[str] = None, using: Optional[UsingType] = None
104
- ) -> None:
105
- """
106
- Create the index and populate the mappings in elasticsearch.
107
- """
108
- i = cls._index
109
- if index:
110
- i = i.clone(name=index)
111
- i.save(using=using)
112
-
113
- @classmethod
114
- def search(
115
- cls, using: Optional[UsingType] = None, index: Optional[str] = None
116
- ) -> Search[Self]:
117
- """
118
- Create an :class:`~elasticsearch.dsl.Search` instance that will search
119
- over this ``Document``.
120
- """
121
- return Search(
122
- using=cls._get_using(using), index=cls._default_index(index), doc_type=[cls]
123
- )
124
-
125
- @classmethod
126
- def get(
127
- cls,
128
- id: str,
129
- using: Optional[UsingType] = None,
130
- index: Optional[str] = None,
131
- **kwargs: Any,
132
- ) -> Optional[Self]:
133
- """
134
- Retrieve a single document from elasticsearch using its ``id``.
135
-
136
- :arg id: ``id`` of the document to be retrieved
137
- :arg index: elasticsearch index to use, if the ``Document`` is
138
- associated with an index this can be omitted.
139
- :arg using: connection alias to use, defaults to ``'default'``
140
-
141
- Any additional keyword arguments will be passed to
142
- ``Elasticsearch.get`` unchanged.
143
- """
144
- es = cls._get_connection(using)
145
- doc = es.get(index=cls._default_index(index), id=id, **kwargs)
146
- if not doc.get("found", False):
147
- return None
148
- return cls.from_es(doc)
149
-
150
- @classmethod
151
- def exists(
152
- cls,
153
- id: str,
154
- using: Optional[UsingType] = None,
155
- index: Optional[str] = None,
156
- **kwargs: Any,
157
- ) -> bool:
158
- """
159
- check if exists a single document from elasticsearch using its ``id``.
160
-
161
- :arg id: ``id`` of the document to check if exists
162
- :arg index: elasticsearch index to use, if the ``Document`` is
163
- associated with an index this can be omitted.
164
- :arg using: connection alias to use, defaults to ``'default'``
165
-
166
- Any additional keyword arguments will be passed to
167
- ``Elasticsearch.exists`` unchanged.
168
- """
169
- es = cls._get_connection(using)
170
- return bool(es.exists(index=cls._default_index(index), id=id, **kwargs))
171
-
172
- @classmethod
173
- def mget(
174
- cls,
175
- docs: List[Dict[str, Any]],
176
- using: Optional[UsingType] = None,
177
- index: Optional[str] = None,
178
- raise_on_error: bool = True,
179
- missing: str = "none",
180
- **kwargs: Any,
181
- ) -> List[Optional[Self]]:
182
- r"""
183
- Retrieve multiple document by their ``id``\s. Returns a list of instances
184
- in the same order as requested.
185
-
186
- :arg docs: list of ``id``\s of the documents to be retrieved or a list
187
- of document specifications as per
188
- https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html
189
- :arg index: elasticsearch index to use, if the ``Document`` is
190
- associated with an index this can be omitted.
191
- :arg using: connection alias to use, defaults to ``'default'``
192
- :arg missing: what to do when one of the documents requested is not
193
- found. Valid options are ``'none'`` (use ``None``), ``'raise'`` (raise
194
- ``NotFoundError``) or ``'skip'`` (ignore the missing document).
195
-
196
- Any additional keyword arguments will be passed to
197
- ``Elasticsearch.mget`` unchanged.
198
- """
199
- if missing not in ("raise", "skip", "none"):
200
- raise ValueError("'missing' must be 'raise', 'skip', or 'none'.")
201
- es = cls._get_connection(using)
202
- body = {
203
- "docs": [
204
- doc if isinstance(doc, collections.abc.Mapping) else {"_id": doc}
205
- for doc in docs
206
- ]
207
- }
208
- results = es.mget(index=cls._default_index(index), body=body, **kwargs)
209
-
210
- objs: List[Optional[Self]] = []
211
- error_docs: List[Self] = []
212
- missing_docs: List[Self] = []
213
- for doc in results["docs"]:
214
- if doc.get("found"):
215
- if error_docs or missing_docs:
216
- # We're going to raise an exception anyway, so avoid an
217
- # expensive call to cls.from_es().
218
- continue
219
-
220
- objs.append(cls.from_es(doc))
221
-
222
- elif doc.get("error"):
223
- if raise_on_error:
224
- error_docs.append(doc)
225
- if missing == "none":
226
- objs.append(None)
227
-
228
- # The doc didn't cause an error, but the doc also wasn't found.
229
- elif missing == "raise":
230
- missing_docs.append(doc)
231
- elif missing == "none":
232
- objs.append(None)
233
-
234
- if error_docs:
235
- error_ids = [doc["_id"] for doc in error_docs]
236
- message = "Required routing not provided for documents %s."
237
- message %= ", ".join(error_ids)
238
- raise RequestError(400, message, error_docs) # type: ignore[arg-type]
239
- if missing_docs:
240
- missing_ids = [doc["_id"] for doc in missing_docs]
241
- message = f"Documents {', '.join(missing_ids)} not found."
242
- raise NotFoundError(404, message, {"docs": missing_docs}) # type: ignore[arg-type]
243
- return objs
244
-
245
- def delete(
246
- self,
247
- using: Optional[UsingType] = None,
248
- index: Optional[str] = None,
249
- **kwargs: Any,
250
- ) -> None:
251
- """
252
- Delete the instance in elasticsearch.
253
-
254
- :arg index: elasticsearch index to use, if the ``Document`` is
255
- associated with an index this can be omitted.
256
- :arg using: connection alias to use, defaults to ``'default'``
257
-
258
- Any additional keyword arguments will be passed to
259
- ``Elasticsearch.delete`` unchanged.
260
- """
261
- es = self._get_connection(using)
262
- # extract routing etc from meta
263
- doc_meta = {k: self.meta[k] for k in DOC_META_FIELDS if k in self.meta}
264
-
265
- # Optimistic concurrency control
266
- if "seq_no" in self.meta and "primary_term" in self.meta:
267
- doc_meta["if_seq_no"] = self.meta["seq_no"]
268
- doc_meta["if_primary_term"] = self.meta["primary_term"]
269
-
270
- doc_meta.update(kwargs)
271
- i = self._get_index(index)
272
- assert i is not None
273
-
274
- es.delete(index=i, **doc_meta)
275
-
276
- def update(
277
- self,
278
- using: Optional[UsingType] = None,
279
- index: Optional[str] = None,
280
- detect_noop: bool = True,
281
- doc_as_upsert: bool = False,
282
- refresh: bool = False,
283
- retry_on_conflict: Optional[int] = None,
284
- script: Optional[Union[str, Dict[str, Any]]] = None,
285
- script_id: Optional[str] = None,
286
- scripted_upsert: bool = False,
287
- upsert: Optional[Dict[str, Any]] = None,
288
- return_doc_meta: bool = False,
289
- **fields: Any,
290
- ) -> Any:
291
- """
292
- Partial update of the document, specify fields you wish to update and
293
- both the instance and the document in elasticsearch will be updated::
294
-
295
- doc = MyDocument(title='Document Title!')
296
- doc.save()
297
- doc.update(title='New Document Title!')
298
-
299
- :arg index: elasticsearch index to use, if the ``Document`` is
300
- associated with an index this can be omitted.
301
- :arg using: connection alias to use, defaults to ``'default'``
302
- :arg detect_noop: Set to ``False`` to disable noop detection.
303
- :arg refresh: Control when the changes made by this request are visible
304
- to search. Set to ``True`` for immediate effect.
305
- :arg retry_on_conflict: In between the get and indexing phases of the
306
- update, it is possible that another process might have already
307
- updated the same document. By default, the update will fail with a
308
- version conflict exception. The retry_on_conflict parameter
309
- controls how many times to retry the update before finally throwing
310
- an exception.
311
- :arg doc_as_upsert: Instead of sending a partial doc plus an upsert
312
- doc, setting doc_as_upsert to true will use the contents of doc as
313
- the upsert value
314
- :arg script: the source code of the script as a string, or a dictionary
315
- with script attributes to update.
316
- :arg return_doc_meta: set to ``True`` to return all metadata from the
317
- index API call instead of only the operation result
318
-
319
- :return: operation result noop/updated
320
- """
321
- body: Dict[str, Any] = {
322
- "doc_as_upsert": doc_as_upsert,
323
- "detect_noop": detect_noop,
324
- }
325
-
326
- # scripted update
327
- if script or script_id:
328
- if upsert is not None:
329
- body["upsert"] = upsert
330
-
331
- if script:
332
- if isinstance(script, str):
333
- script = {"source": script}
334
- else:
335
- script = {"id": script_id}
336
-
337
- if "params" not in script:
338
- script["params"] = fields
339
- else:
340
- script["params"].update(fields)
341
-
342
- body["script"] = script
343
- body["scripted_upsert"] = scripted_upsert
344
-
345
- # partial document update
346
- else:
347
- if not fields:
348
- raise IllegalOperation(
349
- "You cannot call update() without updating individual fields or a script. "
350
- "If you wish to update the entire object use save()."
351
- )
352
-
353
- # update given fields locally
354
- merge(self, fields)
355
-
356
- # prepare data for ES
357
- values = self.to_dict(skip_empty=False)
358
-
359
- # if fields were given: partial update
360
- body["doc"] = {k: values.get(k) for k in fields.keys()}
361
-
362
- # extract routing etc from meta
363
- doc_meta = {k: self.meta[k] for k in DOC_META_FIELDS if k in self.meta}
364
-
365
- if retry_on_conflict is not None:
366
- doc_meta["retry_on_conflict"] = retry_on_conflict
367
-
368
- # Optimistic concurrency control
369
- if (
370
- retry_on_conflict in (None, 0)
371
- and "seq_no" in self.meta
372
- and "primary_term" in self.meta
373
- ):
374
- doc_meta["if_seq_no"] = self.meta["seq_no"]
375
- doc_meta["if_primary_term"] = self.meta["primary_term"]
376
-
377
- i = self._get_index(index)
378
- assert i is not None
379
-
380
- meta = self._get_connection(using).update(
381
- index=i, body=body, refresh=refresh, **doc_meta
382
- )
383
-
384
- # update meta information from ES
385
- for k in META_FIELDS:
386
- if "_" + k in meta:
387
- setattr(self.meta, k, meta["_" + k])
388
-
389
- return meta if return_doc_meta else meta["result"]
390
-
391
- def save(
392
- self,
393
- using: Optional[UsingType] = None,
394
- index: Optional[str] = None,
395
- validate: bool = True,
396
- skip_empty: bool = True,
397
- return_doc_meta: bool = False,
398
- **kwargs: Any,
399
- ) -> Any:
400
- """
401
- Save the document into elasticsearch. If the document doesn't exist it
402
- is created, it is overwritten otherwise. Returns ``True`` if this
403
- operations resulted in new document being created.
404
-
405
- :arg index: elasticsearch index to use, if the ``Document`` is
406
- associated with an index this can be omitted.
407
- :arg using: connection alias to use, defaults to ``'default'``
408
- :arg validate: set to ``False`` to skip validating the document
409
- :arg skip_empty: if set to ``False`` will cause empty values (``None``,
410
- ``[]``, ``{}``) to be left on the document. Those values will be
411
- stripped out otherwise as they make no difference in elasticsearch.
412
- :arg return_doc_meta: set to ``True`` to return all metadata from the
413
- update API call instead of only the operation result
414
-
415
- Any additional keyword arguments will be passed to
416
- ``Elasticsearch.index`` unchanged.
417
-
418
- :return: operation result created/updated
419
- """
420
- if validate:
421
- self.full_clean()
422
-
423
- es = self._get_connection(using)
424
- # extract routing etc from meta
425
- doc_meta = {k: self.meta[k] for k in DOC_META_FIELDS if k in self.meta}
426
-
427
- # Optimistic concurrency control
428
- if "seq_no" in self.meta and "primary_term" in self.meta:
429
- doc_meta["if_seq_no"] = self.meta["seq_no"]
430
- doc_meta["if_primary_term"] = self.meta["primary_term"]
431
-
432
- doc_meta.update(kwargs)
433
- i = self._get_index(index)
434
- assert i is not None
435
-
436
- meta = es.index(
437
- index=i,
438
- body=self.to_dict(skip_empty=skip_empty),
439
- **doc_meta,
440
- )
441
- # update meta information from ES
442
- for k in META_FIELDS:
443
- if "_" + k in meta:
444
- setattr(self.meta, k, meta["_" + k])
445
-
446
- return meta if return_doc_meta else meta["result"]
447
-
448
- @classmethod
449
- def bulk(
450
- cls,
451
- actions: Iterable[Union[Self, Dict[str, Any]]],
452
- using: Optional[UsingType] = None,
453
- index: Optional[str] = None,
454
- validate: bool = True,
455
- skip_empty: bool = True,
456
- **kwargs: Any,
457
- ) -> Tuple[int, Union[int, List[Any]]]:
458
- """
459
- Allows to perform multiple indexing operations in a single request.
460
-
461
- :arg actions: a generator that returns document instances to be indexed,
462
- bulk operation dictionaries.
463
- :arg using: connection alias to use, defaults to ``'default'``
464
- :arg index: Elasticsearch index to use, if the ``Document`` is
465
- associated with an index this can be omitted.
466
- :arg validate: set to ``False`` to skip validating the documents
467
- :arg skip_empty: if set to ``False`` will cause empty values (``None``,
468
- ``[]``, ``{}``) to be left on the document. Those values will be
469
- stripped out otherwise as they make no difference in Elasticsearch.
470
-
471
- Any additional keyword arguments will be passed to
472
- ``Elasticsearch.bulk`` unchanged.
473
-
474
- :return: bulk operation results
475
- """
476
- es = cls._get_connection(using)
477
-
478
- i = cls._default_index(index)
479
- assert i is not None
480
-
481
- class Generate:
482
- def __init__(
483
- self,
484
- doc_iterator: Iterable[Union[Document, Dict[str, Any]]],
485
- ):
486
- self.doc_iterator = doc_iterator.__iter__()
487
-
488
- def __iter__(self) -> Self:
489
- return self
490
-
491
- def __next__(self) -> Dict[str, Any]:
492
- doc: Optional[Union[Document, Dict[str, Any]]] = (
493
- self.doc_iterator.__next__()
494
- )
495
-
496
- if isinstance(doc, dict):
497
- action = doc
498
- doc = None
499
- if "_source" in action and isinstance(action["_source"], Document):
500
- doc = action["_source"]
501
- if validate: # pragma: no cover
502
- doc.full_clean()
503
- action["_source"] = doc.to_dict(
504
- include_meta=False, skip_empty=skip_empty
505
- )
506
- elif doc is not None:
507
- if validate: # pragma: no cover
508
- doc.full_clean()
509
- action = doc.to_dict(include_meta=True, skip_empty=skip_empty)
510
- if "_index" not in action:
511
- action["_index"] = i
512
- return action
513
-
514
- return bulk(es, Generate(actions), **kwargs)
@@ -1,50 +0,0 @@
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
- from typing import TYPE_CHECKING
19
-
20
- from ..faceted_search_base import FacetedResponse, FacetedSearchBase
21
- from ..utils import _R
22
- from .search import Search
23
-
24
- if TYPE_CHECKING:
25
- from ..response import Response
26
-
27
-
28
- class FacetedSearch(FacetedSearchBase[_R]):
29
- _s: Search[_R]
30
-
31
- def count(self) -> int:
32
- return self._s.count()
33
-
34
- def search(self) -> Search[_R]:
35
- """
36
- Returns the base Search object to which the facets are added.
37
-
38
- You can customize the query by overriding this method and returning a
39
- modified search object.
40
- """
41
- s = Search[_R](doc_type=self.doc_types, index=self.index, using=self.using)
42
- return s.response_class(FacetedResponse)
43
-
44
- def execute(self) -> "Response[_R]":
45
- """
46
- Execute the search and return the response.
47
- """
48
- r = self._s.execute()
49
- r._faceted_search = self
50
- return r