elasticsearch 8.18.1__py3-none-any.whl → 8.19.1__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 (102) hide show
  1. elasticsearch/_async/client/__init__.py +68 -82
  2. elasticsearch/_async/client/async_search.py +5 -9
  3. elasticsearch/_async/client/autoscaling.py +4 -4
  4. elasticsearch/_async/client/cat.py +744 -75
  5. elasticsearch/_async/client/ccr.py +13 -13
  6. elasticsearch/_async/client/cluster.py +38 -24
  7. elasticsearch/_async/client/connector.py +30 -30
  8. elasticsearch/_async/client/dangling_indices.py +3 -3
  9. elasticsearch/_async/client/enrich.py +5 -5
  10. elasticsearch/_async/client/eql.py +13 -5
  11. elasticsearch/_async/client/esql.py +54 -15
  12. elasticsearch/_async/client/features.py +2 -2
  13. elasticsearch/_async/client/fleet.py +13 -13
  14. elasticsearch/_async/client/graph.py +1 -1
  15. elasticsearch/_async/client/ilm.py +11 -11
  16. elasticsearch/_async/client/indices.py +132 -83
  17. elasticsearch/_async/client/inference.py +519 -112
  18. elasticsearch/_async/client/ingest.py +9 -16
  19. elasticsearch/_async/client/license.py +10 -10
  20. elasticsearch/_async/client/logstash.py +3 -3
  21. elasticsearch/_async/client/migration.py +3 -3
  22. elasticsearch/_async/client/ml.py +76 -88
  23. elasticsearch/_async/client/nodes.py +9 -8
  24. elasticsearch/_async/client/query_rules.py +8 -8
  25. elasticsearch/_async/client/rollup.py +8 -8
  26. elasticsearch/_async/client/search_application.py +10 -10
  27. elasticsearch/_async/client/searchable_snapshots.py +4 -4
  28. elasticsearch/_async/client/security.py +72 -80
  29. elasticsearch/_async/client/shutdown.py +3 -3
  30. elasticsearch/_async/client/simulate.py +1 -1
  31. elasticsearch/_async/client/slm.py +9 -9
  32. elasticsearch/_async/client/snapshot.py +286 -130
  33. elasticsearch/_async/client/sql.py +7 -7
  34. elasticsearch/_async/client/ssl.py +1 -1
  35. elasticsearch/_async/client/synonyms.py +7 -7
  36. elasticsearch/_async/client/tasks.py +3 -3
  37. elasticsearch/_async/client/text_structure.py +4 -4
  38. elasticsearch/_async/client/transform.py +69 -9
  39. elasticsearch/_async/client/xpack.py +1 -1
  40. elasticsearch/_sync/client/__init__.py +68 -82
  41. elasticsearch/_sync/client/async_search.py +5 -9
  42. elasticsearch/_sync/client/autoscaling.py +4 -4
  43. elasticsearch/_sync/client/cat.py +744 -75
  44. elasticsearch/_sync/client/ccr.py +13 -13
  45. elasticsearch/_sync/client/cluster.py +38 -24
  46. elasticsearch/_sync/client/connector.py +30 -30
  47. elasticsearch/_sync/client/dangling_indices.py +3 -3
  48. elasticsearch/_sync/client/enrich.py +5 -5
  49. elasticsearch/_sync/client/eql.py +13 -5
  50. elasticsearch/_sync/client/esql.py +54 -15
  51. elasticsearch/_sync/client/features.py +2 -2
  52. elasticsearch/_sync/client/fleet.py +13 -13
  53. elasticsearch/_sync/client/graph.py +1 -1
  54. elasticsearch/_sync/client/ilm.py +11 -11
  55. elasticsearch/_sync/client/indices.py +132 -83
  56. elasticsearch/_sync/client/inference.py +519 -112
  57. elasticsearch/_sync/client/ingest.py +9 -16
  58. elasticsearch/_sync/client/license.py +10 -10
  59. elasticsearch/_sync/client/logstash.py +3 -3
  60. elasticsearch/_sync/client/migration.py +3 -3
  61. elasticsearch/_sync/client/ml.py +76 -88
  62. elasticsearch/_sync/client/nodes.py +9 -8
  63. elasticsearch/_sync/client/query_rules.py +8 -8
  64. elasticsearch/_sync/client/rollup.py +8 -8
  65. elasticsearch/_sync/client/search_application.py +10 -10
  66. elasticsearch/_sync/client/searchable_snapshots.py +4 -4
  67. elasticsearch/_sync/client/security.py +72 -80
  68. elasticsearch/_sync/client/shutdown.py +3 -3
  69. elasticsearch/_sync/client/simulate.py +1 -1
  70. elasticsearch/_sync/client/slm.py +9 -9
  71. elasticsearch/_sync/client/snapshot.py +286 -130
  72. elasticsearch/_sync/client/sql.py +7 -7
  73. elasticsearch/_sync/client/ssl.py +1 -1
  74. elasticsearch/_sync/client/synonyms.py +7 -7
  75. elasticsearch/_sync/client/tasks.py +3 -3
  76. elasticsearch/_sync/client/text_structure.py +4 -4
  77. elasticsearch/_sync/client/transform.py +69 -9
  78. elasticsearch/_sync/client/xpack.py +1 -1
  79. elasticsearch/_version.py +1 -1
  80. elasticsearch/compat.py +5 -0
  81. elasticsearch/dsl/__init__.py +2 -1
  82. elasticsearch/dsl/_async/document.py +85 -1
  83. elasticsearch/dsl/_sync/document.py +85 -1
  84. elasticsearch/dsl/aggs.py +22 -3
  85. elasticsearch/dsl/document_base.py +219 -16
  86. elasticsearch/dsl/field.py +272 -48
  87. elasticsearch/dsl/query.py +49 -4
  88. elasticsearch/dsl/response/aggs.py +1 -1
  89. elasticsearch/dsl/types.py +247 -27
  90. elasticsearch/dsl/utils.py +2 -2
  91. elasticsearch/esql/__init__.py +19 -0
  92. elasticsearch/esql/esql.py +1156 -0
  93. elasticsearch/esql/functions.py +1750 -0
  94. elasticsearch/exceptions.py +2 -0
  95. {elasticsearch-8.18.1.dist-info → elasticsearch-8.19.1.dist-info}/METADATA +1 -5
  96. elasticsearch-8.19.1.dist-info/RECORD +164 -0
  97. elasticsearch-8.18.1.dist-info/RECORD +0 -163
  98. elasticsearch-8.18.1.dist-info/licenses/LICENSE.txt +0 -175
  99. elasticsearch-8.18.1.dist-info/licenses/NOTICE.txt +0 -559
  100. {elasticsearch-8.18.1.dist-info → elasticsearch-8.19.1.dist-info}/WHEEL +0 -0
  101. {elasticsearch-8.18.1.dist-info → elasticsearch-8.19.1.dist-info}/licenses/LICENSE +0 -0
  102. {elasticsearch-8.18.1.dist-info → elasticsearch-8.19.1.dist-info}/licenses/NOTICE +0 -0
elasticsearch/dsl/aggs.py CHANGED
@@ -372,6 +372,12 @@ class Boxplot(Agg[_R]):
372
372
  :arg compression: Limits the maximum number of nodes used by the
373
373
  underlying TDigest algorithm to `20 * compression`, enabling
374
374
  control of memory usage and approximation error.
375
+ :arg execution_hint: The default implementation of TDigest is
376
+ optimized for performance, scaling to millions or even billions of
377
+ sample values while maintaining acceptable accuracy levels (close
378
+ to 1% relative error for millions of samples in some cases). To
379
+ use an implementation optimized for accuracy, set this parameter
380
+ to high_accuracy instead. Defaults to `default` if omitted.
375
381
  :arg field: The field on which to run the aggregation.
376
382
  :arg missing: The value to apply to documents that do not have a
377
383
  value. By default, documents without a value are ignored.
@@ -384,6 +390,9 @@ class Boxplot(Agg[_R]):
384
390
  self,
385
391
  *,
386
392
  compression: Union[float, "DefaultType"] = DEFAULT,
393
+ execution_hint: Union[
394
+ Literal["default", "high_accuracy"], "DefaultType"
395
+ ] = DEFAULT,
387
396
  field: Union[str, "InstrumentedField", "DefaultType"] = DEFAULT,
388
397
  missing: Union[str, int, float, bool, "DefaultType"] = DEFAULT,
389
398
  script: Union["types.Script", Dict[str, Any], "DefaultType"] = DEFAULT,
@@ -391,6 +400,7 @@ class Boxplot(Agg[_R]):
391
400
  ):
392
401
  super().__init__(
393
402
  compression=compression,
403
+ execution_hint=execution_hint,
394
404
  field=field,
395
405
  missing=missing,
396
406
  script=script,
@@ -678,9 +688,8 @@ class CategorizeText(Bucket[_R]):
678
688
  :arg categorization_analyzer: The categorization analyzer specifies
679
689
  how the text is analyzed and tokenized before being categorized.
680
690
  The syntax is very similar to that used to define the analyzer in
681
- the [Analyze endpoint](https://www.elastic.co/guide/en/elasticsear
682
- ch/reference/8.0/indices-analyze.html). This property cannot be
683
- used at the same time as categorization_filters.
691
+ the `_analyze` endpoint. This property cannot be used at the same
692
+ time as categorization_filters.
684
693
  :arg shard_size: The number of categorization buckets to return from
685
694
  each shard before merging all the results.
686
695
  :arg size: The number of buckets to return. Defaults to `10` if
@@ -1898,6 +1907,12 @@ class MedianAbsoluteDeviation(Agg[_R]):
1898
1907
  underlying TDigest algorithm to `20 * compression`, enabling
1899
1908
  control of memory usage and approximation error. Defaults to
1900
1909
  `1000` if omitted.
1910
+ :arg execution_hint: The default implementation of TDigest is
1911
+ optimized for performance, scaling to millions or even billions of
1912
+ sample values while maintaining acceptable accuracy levels (close
1913
+ to 1% relative error for millions of samples in some cases). To
1914
+ use an implementation optimized for accuracy, set this parameter
1915
+ to high_accuracy instead. Defaults to `default` if omitted.
1901
1916
  :arg format:
1902
1917
  :arg field: The field on which to run the aggregation.
1903
1918
  :arg missing: The value to apply to documents that do not have a
@@ -1911,6 +1926,9 @@ class MedianAbsoluteDeviation(Agg[_R]):
1911
1926
  self,
1912
1927
  *,
1913
1928
  compression: Union[float, "DefaultType"] = DEFAULT,
1929
+ execution_hint: Union[
1930
+ Literal["default", "high_accuracy"], "DefaultType"
1931
+ ] = DEFAULT,
1914
1932
  format: Union[str, "DefaultType"] = DEFAULT,
1915
1933
  field: Union[str, "InstrumentedField", "DefaultType"] = DEFAULT,
1916
1934
  missing: Union[str, int, float, bool, "DefaultType"] = DEFAULT,
@@ -1919,6 +1937,7 @@ class MedianAbsoluteDeviation(Agg[_R]):
1919
1937
  ):
1920
1938
  super().__init__(
1921
1939
  compression=compression,
1940
+ execution_hint=execution_hint,
1922
1941
  format=format,
1923
1942
  field=field,
1924
1943
  missing=missing,
@@ -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 (
@@ -27,6 +28,7 @@ from typing import (
27
28
  List,
28
29
  Optional,
29
30
  Tuple,
31
+ Type,
30
32
  TypeVar,
31
33
  Union,
32
34
  get_args,
@@ -48,6 +50,7 @@ from .utils import DOC_META_FIELDS, ObjectBase
48
50
  if TYPE_CHECKING:
49
51
  from elastic_transport import ObjectApiResponse
50
52
 
53
+ from ..esql.esql import ESQLBase
51
54
  from .index_base import IndexBase
52
55
 
53
56
 
@@ -56,7 +59,163 @@ class MetaField:
56
59
  self.args, self.kwargs = args, kwargs
57
60
 
58
61
 
59
- class InstrumentedField:
62
+ class InstrumentedExpression:
63
+ """Proxy object for a ES|QL expression."""
64
+
65
+ def __init__(self, expr: str):
66
+ self._expr = expr
67
+
68
+ def _render_value(self, value: Any) -> str:
69
+ if isinstance(value, InstrumentedExpression):
70
+ return str(value)
71
+ return json.dumps(value)
72
+
73
+ def __str__(self) -> str:
74
+ return self._expr
75
+
76
+ def __repr__(self) -> str:
77
+ return f"InstrumentedExpression[{self._expr}]"
78
+
79
+ def __pos__(self) -> "InstrumentedExpression":
80
+ return self
81
+
82
+ def __neg__(self) -> "InstrumentedExpression":
83
+ return InstrumentedExpression(f"-({self._expr})")
84
+
85
+ def __eq__(self, value: Any) -> "InstrumentedExpression": # type: ignore[override]
86
+ return InstrumentedExpression(f"{self._expr} == {self._render_value(value)}")
87
+
88
+ def __ne__(self, value: Any) -> "InstrumentedExpression": # type: ignore[override]
89
+ return InstrumentedExpression(f"{self._expr} != {self._render_value(value)}")
90
+
91
+ def __lt__(self, value: Any) -> "InstrumentedExpression":
92
+ return InstrumentedExpression(f"{self._expr} < {self._render_value(value)}")
93
+
94
+ def __gt__(self, value: Any) -> "InstrumentedExpression":
95
+ return InstrumentedExpression(f"{self._expr} > {self._render_value(value)}")
96
+
97
+ def __le__(self, value: Any) -> "InstrumentedExpression":
98
+ return InstrumentedExpression(f"{self._expr} <= {self._render_value(value)}")
99
+
100
+ def __ge__(self, value: Any) -> "InstrumentedExpression":
101
+ return InstrumentedExpression(f"{self._expr} >= {self._render_value(value)}")
102
+
103
+ def __add__(self, value: Any) -> "InstrumentedExpression":
104
+ return InstrumentedExpression(f"{self._expr} + {self._render_value(value)}")
105
+
106
+ def __radd__(self, value: Any) -> "InstrumentedExpression":
107
+ return InstrumentedExpression(f"{self._render_value(value)} + {self._expr}")
108
+
109
+ def __sub__(self, value: Any) -> "InstrumentedExpression":
110
+ return InstrumentedExpression(f"{self._expr} - {self._render_value(value)}")
111
+
112
+ def __rsub__(self, value: Any) -> "InstrumentedExpression":
113
+ return InstrumentedExpression(f"{self._render_value(value)} - {self._expr}")
114
+
115
+ def __mul__(self, value: Any) -> "InstrumentedExpression":
116
+ return InstrumentedExpression(f"{self._expr} * {self._render_value(value)}")
117
+
118
+ def __rmul__(self, value: Any) -> "InstrumentedExpression":
119
+ return InstrumentedExpression(f"{self._render_value(value)} * {self._expr}")
120
+
121
+ def __truediv__(self, value: Any) -> "InstrumentedExpression":
122
+ return InstrumentedExpression(f"{self._expr} / {self._render_value(value)}")
123
+
124
+ def __rtruediv__(self, value: Any) -> "InstrumentedExpression":
125
+ return InstrumentedExpression(f"{self._render_value(value)} / {self._expr}")
126
+
127
+ def __mod__(self, value: Any) -> "InstrumentedExpression":
128
+ return InstrumentedExpression(f"{self._expr} % {self._render_value(value)}")
129
+
130
+ def __rmod__(self, value: Any) -> "InstrumentedExpression":
131
+ return InstrumentedExpression(f"{self._render_value(value)} % {self._expr}")
132
+
133
+ def is_null(self) -> "InstrumentedExpression":
134
+ """Compare the expression against NULL."""
135
+ return InstrumentedExpression(f"{self._expr} IS NULL")
136
+
137
+ def is_not_null(self) -> "InstrumentedExpression":
138
+ """Compare the expression against NOT NULL."""
139
+ return InstrumentedExpression(f"{self._expr} IS NOT NULL")
140
+
141
+ def in_(self, *values: Any) -> "InstrumentedExpression":
142
+ """Test if the expression equals one of the given values."""
143
+ rendered_values = ", ".join([f"{value}" for value in values])
144
+ return InstrumentedExpression(f"{self._expr} IN ({rendered_values})")
145
+
146
+ def like(self, *patterns: str) -> "InstrumentedExpression":
147
+ """Filter the expression using a string pattern."""
148
+ if len(patterns) == 1:
149
+ return InstrumentedExpression(
150
+ f"{self._expr} LIKE {self._render_value(patterns[0])}"
151
+ )
152
+ else:
153
+ return InstrumentedExpression(
154
+ f'{self._expr} LIKE ({", ".join([self._render_value(p) for p in patterns])})'
155
+ )
156
+
157
+ def rlike(self, *patterns: str) -> "InstrumentedExpression":
158
+ """Filter the expression using a regular expression."""
159
+ if len(patterns) == 1:
160
+ return InstrumentedExpression(
161
+ f"{self._expr} RLIKE {self._render_value(patterns[0])}"
162
+ )
163
+ else:
164
+ return InstrumentedExpression(
165
+ f'{self._expr} RLIKE ({", ".join([self._render_value(p) for p in patterns])})'
166
+ )
167
+
168
+ def match(self, query: str) -> "InstrumentedExpression":
169
+ """Perform a match query on the field."""
170
+ return InstrumentedExpression(f"{self._expr}:{self._render_value(query)}")
171
+
172
+ def asc(self) -> "InstrumentedExpression":
173
+ """Return the field name representation for ascending sort order.
174
+
175
+ For use in ES|QL queries only.
176
+ """
177
+ return InstrumentedExpression(f"{self._expr} ASC")
178
+
179
+ def desc(self) -> "InstrumentedExpression":
180
+ """Return the field name representation for descending sort order.
181
+
182
+ For use in ES|QL queries only.
183
+ """
184
+ return InstrumentedExpression(f"{self._expr} DESC")
185
+
186
+ def nulls_first(self) -> "InstrumentedExpression":
187
+ """Return the field name representation for nulls first sort order.
188
+
189
+ For use in ES|QL queries only.
190
+ """
191
+ return InstrumentedExpression(f"{self._expr} NULLS FIRST")
192
+
193
+ def nulls_last(self) -> "InstrumentedExpression":
194
+ """Return the field name representation for nulls last sort order.
195
+
196
+ For use in ES|QL queries only.
197
+ """
198
+ return InstrumentedExpression(f"{self._expr} NULLS LAST")
199
+
200
+ def where(
201
+ self, *expressions: Union[str, "InstrumentedExpression"]
202
+ ) -> "InstrumentedExpression":
203
+ """Add a condition to be met for the row to be included.
204
+
205
+ Use only in expressions given in the ``STATS`` command.
206
+ """
207
+ if len(expressions) == 1:
208
+ return InstrumentedExpression(f"{self._expr} WHERE {expressions[0]}")
209
+ else:
210
+ return InstrumentedExpression(
211
+ f'{self._expr} WHERE {" AND ".join([f"({expr})" for expr in expressions])}'
212
+ )
213
+
214
+
215
+ E = InstrumentedExpression
216
+
217
+
218
+ class InstrumentedField(InstrumentedExpression):
60
219
  """Proxy object for a mapped document field.
61
220
 
62
221
  An object of this instance is returned when a field is accessed as a class
@@ -71,8 +230,8 @@ class InstrumentedField:
71
230
  s = s.sort(-MyDocument.name) # sort by name in descending order
72
231
  """
73
232
 
74
- def __init__(self, name: str, field: Field):
75
- self._name = name
233
+ def __init__(self, name: str, field: Optional[Field]):
234
+ super().__init__(name)
76
235
  self._field = field
77
236
 
78
237
  # note that the return value type here assumes classes will only be used to
@@ -83,26 +242,29 @@ class InstrumentedField:
83
242
  # first let's see if this is an attribute of this object
84
243
  return super().__getattribute__(attr) # type: ignore[no-any-return]
85
244
  except AttributeError:
86
- try:
87
- # next we see if we have a sub-field with this name
88
- return InstrumentedField(f"{self._name}.{attr}", self._field[attr])
89
- except KeyError:
90
- # lastly we let the wrapped field resolve this attribute
91
- return getattr(self._field, attr) # type: ignore[no-any-return]
92
-
93
- def __pos__(self) -> str:
245
+ if self._field:
246
+ try:
247
+ # next we see if we have a sub-field with this name
248
+ return InstrumentedField(f"{self._expr}.{attr}", self._field[attr])
249
+ except KeyError:
250
+ # lastly we let the wrapped field resolve this attribute
251
+ return getattr(self._field, attr) # type: ignore[no-any-return]
252
+ else:
253
+ raise
254
+
255
+ def __pos__(self) -> str: # type: ignore[override]
94
256
  """Return the field name representation for ascending sort order"""
95
- return f"{self._name}"
257
+ return f"{self._expr}"
96
258
 
97
- def __neg__(self) -> str:
259
+ def __neg__(self) -> str: # type: ignore[override]
98
260
  """Return the field name representation for descending sort order"""
99
- return f"-{self._name}"
261
+ return f"-{self._expr}"
100
262
 
101
263
  def __str__(self) -> str:
102
- return self._name
264
+ return self._expr
103
265
 
104
266
  def __repr__(self) -> str:
105
- return f"InstrumentedField[{self._name}]"
267
+ return f"InstrumentedField[{self._expr}]"
106
268
 
107
269
 
108
270
  class DocumentMeta(type):
@@ -442,3 +604,44 @@ class DocumentBase(ObjectBase):
442
604
 
443
605
  meta["_source"] = d
444
606
  return meta
607
+
608
+ @classmethod
609
+ def _get_field_names(
610
+ cls, for_esql: bool = False, nested_class: Optional[Type[InnerDoc]] = None
611
+ ) -> List[str]:
612
+ """Return the list of field names used by this document.
613
+ If the document has nested objects, their fields are reported using dot
614
+ notation. If the ``for_esql`` argument is set to ``True``, the list omits
615
+ nested fields, which are currently unsupported in ES|QL.
616
+ """
617
+ fields = []
618
+ class_ = nested_class or cls
619
+ for field_name in class_._doc_type.mapping:
620
+ field = class_._doc_type.mapping[field_name]
621
+ if isinstance(field, Object):
622
+ if for_esql and isinstance(field, Nested):
623
+ # ES|QL does not recognize Nested fields at this time
624
+ continue
625
+ sub_fields = cls._get_field_names(
626
+ for_esql=for_esql, nested_class=field._doc_class
627
+ )
628
+ for sub_field in sub_fields:
629
+ fields.append(f"{field_name}.{sub_field}")
630
+ else:
631
+ fields.append(field_name)
632
+ return fields
633
+
634
+ @classmethod
635
+ def esql_from(cls) -> "ESQLBase":
636
+ """Return a base ES|QL query for instances of this document class.
637
+
638
+ The returned query is initialized with ``FROM`` and ``KEEP`` statements,
639
+ and can be completed as desired.
640
+ """
641
+ from ..esql import ESQL # here to avoid circular imports
642
+
643
+ return (
644
+ ESQL.from_(cls)
645
+ .metadata("_id")
646
+ .keep("_id", *tuple(cls._get_field_names(for_esql=True)))
647
+ )