meilisearch-python-sdk 2.0.0__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.
Potentially problematic release.
This version of meilisearch-python-sdk might be problematic. Click here for more details.
- meilisearch_python_sdk/__init__.py +8 -0
- meilisearch_python_sdk/_client.py +1762 -0
- meilisearch_python_sdk/_http_requests.py +138 -0
- meilisearch_python_sdk/_index.py +5620 -0
- meilisearch_python_sdk/_task.py +358 -0
- meilisearch_python_sdk/_utils.py +50 -0
- meilisearch_python_sdk/_version.py +1 -0
- meilisearch_python_sdk/errors.py +71 -0
- meilisearch_python_sdk/models/__init__.py +0 -0
- meilisearch_python_sdk/models/client.py +159 -0
- meilisearch_python_sdk/models/documents.py +10 -0
- meilisearch_python_sdk/models/health.py +5 -0
- meilisearch_python_sdk/models/index.py +67 -0
- meilisearch_python_sdk/models/search.py +59 -0
- meilisearch_python_sdk/models/settings.py +72 -0
- meilisearch_python_sdk/models/task.py +109 -0
- meilisearch_python_sdk/models/version.py +10 -0
- meilisearch_python_sdk/py.typed +0 -0
- meilisearch_python_sdk-2.0.0.dist-info/LICENSE +21 -0
- meilisearch_python_sdk-2.0.0.dist-info/METADATA +253 -0
- meilisearch_python_sdk-2.0.0.dist-info/RECORD +22 -0
- meilisearch_python_sdk-2.0.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1762 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from ssl import SSLContext
|
|
6
|
+
from types import TracebackType
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import jwt
|
|
10
|
+
from httpx import AsyncClient as HttpxAsyncClient
|
|
11
|
+
from httpx import Client as HttpxClient
|
|
12
|
+
|
|
13
|
+
from meilisearch_python_sdk import _task
|
|
14
|
+
from meilisearch_python_sdk._http_requests import AsyncHttpRequests, HttpRequests
|
|
15
|
+
from meilisearch_python_sdk._index import AsyncIndex, Index
|
|
16
|
+
from meilisearch_python_sdk._utils import is_pydantic_2
|
|
17
|
+
from meilisearch_python_sdk.errors import InvalidRestriction, MeilisearchApiError
|
|
18
|
+
from meilisearch_python_sdk.models.client import (
|
|
19
|
+
ClientStats,
|
|
20
|
+
Key,
|
|
21
|
+
KeyCreate,
|
|
22
|
+
KeySearch,
|
|
23
|
+
KeyUpdate,
|
|
24
|
+
)
|
|
25
|
+
from meilisearch_python_sdk.models.health import Health
|
|
26
|
+
from meilisearch_python_sdk.models.index import IndexInfo
|
|
27
|
+
from meilisearch_python_sdk.models.search import SearchParams, SearchResultsWithUID
|
|
28
|
+
from meilisearch_python_sdk.models.task import TaskInfo, TaskResult, TaskStatus
|
|
29
|
+
from meilisearch_python_sdk.models.version import Version
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BaseClient:
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
api_key: str | None = None,
|
|
36
|
+
) -> None:
|
|
37
|
+
self._headers: dict[str, str] | None
|
|
38
|
+
if api_key:
|
|
39
|
+
self._headers = {"Authorization": f"Bearer {api_key}"}
|
|
40
|
+
else:
|
|
41
|
+
self._headers = None
|
|
42
|
+
|
|
43
|
+
def generate_tenant_token(
|
|
44
|
+
self,
|
|
45
|
+
search_rules: dict[str, Any] | list[str],
|
|
46
|
+
*,
|
|
47
|
+
api_key: Key,
|
|
48
|
+
expires_at: datetime | None = None,
|
|
49
|
+
) -> str:
|
|
50
|
+
"""Generates a JWT token to use for searching.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
|
|
54
|
+
search_rules: Contains restrictions to use for the token. The default rules used for
|
|
55
|
+
the API key used for signing can be used by setting searchRules to ["*"]. If "indexes"
|
|
56
|
+
is included it must be equal to or more restrictive than the key used to generate the
|
|
57
|
+
token.
|
|
58
|
+
api_key: The API key to use to generate the token.
|
|
59
|
+
expires_at: The timepoint at which the token should expire. If value is provided it
|
|
60
|
+
shoud be a UTC time in the future. Default = None.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
|
|
64
|
+
A JWT token
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
|
|
68
|
+
InvalidRestriction: If the restrictions are less strict than the permissions allowed
|
|
69
|
+
in the API key.
|
|
70
|
+
KeyNotFoundError: If no API search key is found.
|
|
71
|
+
|
|
72
|
+
Examples:
|
|
73
|
+
|
|
74
|
+
Async:
|
|
75
|
+
|
|
76
|
+
>>> from datetime import datetime, timedelta, timezone
|
|
77
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
78
|
+
>>>
|
|
79
|
+
>>> expires_at = datetime.now(tz=timezone.utc) + timedelta(days=7)
|
|
80
|
+
>>>
|
|
81
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
82
|
+
>>> token = client.generate_tenant_token(
|
|
83
|
+
>>> search_rules = ["*"], api_key=api_key, expires_at=expires_at
|
|
84
|
+
>>> )
|
|
85
|
+
|
|
86
|
+
Sync:
|
|
87
|
+
|
|
88
|
+
>>> from datetime import datetime, timedelta, timezone
|
|
89
|
+
>>> from meilisearch_python_sdk import Client
|
|
90
|
+
>>>
|
|
91
|
+
>>> expires_at = datetime.now(tz=timezone.utc) + timedelta(days=7)
|
|
92
|
+
>>>
|
|
93
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
94
|
+
>>> token = client.generate_tenant_token(
|
|
95
|
+
>>> search_rules = ["*"], api_key=api_key, expires_at=expires_at
|
|
96
|
+
>>> )
|
|
97
|
+
"""
|
|
98
|
+
if isinstance(search_rules, dict) and search_rules.get("indexes"):
|
|
99
|
+
for index in search_rules["indexes"]:
|
|
100
|
+
if api_key.indexes != ["*"] and index not in api_key.indexes:
|
|
101
|
+
raise InvalidRestriction(
|
|
102
|
+
"Invalid index. The token cannot be less restrictive than the API key"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
payload: dict[str, Any] = {"searchRules": search_rules}
|
|
106
|
+
|
|
107
|
+
payload["apiKeyUid"] = api_key.uid
|
|
108
|
+
if expires_at:
|
|
109
|
+
if expires_at <= datetime.now(tz=timezone.utc):
|
|
110
|
+
raise ValueError("expires_at must be a time in the future")
|
|
111
|
+
|
|
112
|
+
payload["exp"] = int(datetime.timestamp(expires_at))
|
|
113
|
+
|
|
114
|
+
return jwt.encode(payload, api_key.key, algorithm="HS256")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class AsyncClient(BaseClient):
|
|
118
|
+
"""Async client to connect to the Meilisearch API."""
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
url: str,
|
|
123
|
+
api_key: str | None = None,
|
|
124
|
+
*,
|
|
125
|
+
timeout: int | None = None,
|
|
126
|
+
verify: str | bool | SSLContext = True,
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Class initializer.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
|
|
132
|
+
url: The url to the Meilisearch API (ex: http://localhost:7700)
|
|
133
|
+
api_key: The optional API key for Meilisearch. Defaults to None.
|
|
134
|
+
timeout: The amount of time in seconds that the client will wait for a response before
|
|
135
|
+
timing out. Defaults to None.
|
|
136
|
+
verify: SSL certificates (a.k.a CA bundle) used to
|
|
137
|
+
verify the identity of requested hosts. Either `True` (default CA bundle),
|
|
138
|
+
a path to an SSL certificate file, or `False` (disable verification)
|
|
139
|
+
"""
|
|
140
|
+
super().__init__(api_key)
|
|
141
|
+
|
|
142
|
+
self.http_client = HttpxAsyncClient(
|
|
143
|
+
base_url=url, timeout=timeout, headers=self._headers, verify=verify
|
|
144
|
+
)
|
|
145
|
+
self._http_requests = AsyncHttpRequests(self.http_client)
|
|
146
|
+
|
|
147
|
+
async def __aenter__(self) -> AsyncClient:
|
|
148
|
+
return self
|
|
149
|
+
|
|
150
|
+
async def __aexit__(
|
|
151
|
+
self,
|
|
152
|
+
et: type[BaseException] | None,
|
|
153
|
+
ev: type[BaseException] | None,
|
|
154
|
+
traceback: TracebackType | None,
|
|
155
|
+
) -> None:
|
|
156
|
+
await self.aclose()
|
|
157
|
+
|
|
158
|
+
async def aclose(self) -> None:
|
|
159
|
+
"""Closes the client.
|
|
160
|
+
|
|
161
|
+
This only needs to be used if the client was not created with a context manager.
|
|
162
|
+
"""
|
|
163
|
+
await self.http_client.aclose()
|
|
164
|
+
|
|
165
|
+
async def create_dump(self) -> TaskInfo:
|
|
166
|
+
"""Trigger the creation of a Meilisearch dump.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
|
|
170
|
+
The details of the task.
|
|
171
|
+
|
|
172
|
+
Raises:
|
|
173
|
+
|
|
174
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
175
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
176
|
+
|
|
177
|
+
Examples:
|
|
178
|
+
|
|
179
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
180
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
181
|
+
>>> await client.create_dump()
|
|
182
|
+
"""
|
|
183
|
+
response = await self._http_requests.post("dumps")
|
|
184
|
+
|
|
185
|
+
return TaskInfo(**response.json())
|
|
186
|
+
|
|
187
|
+
async def create_index(self, uid: str, primary_key: str | None = None) -> AsyncIndex:
|
|
188
|
+
"""Creates a new index.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
|
|
192
|
+
uid: The index's unique identifier.
|
|
193
|
+
primary_key: The primary key of the documents. Defaults to None.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
|
|
197
|
+
An instance of AsyncIndex containing the information of the newly created index.
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
|
|
201
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
202
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
203
|
+
|
|
204
|
+
Examples:
|
|
205
|
+
|
|
206
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
207
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
208
|
+
>>> index = await client.create_index("movies")
|
|
209
|
+
"""
|
|
210
|
+
return await AsyncIndex.create(self.http_client, uid, primary_key)
|
|
211
|
+
|
|
212
|
+
async def delete_index_if_exists(self, uid: str) -> bool:
|
|
213
|
+
"""Deletes an index if it already exists.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
|
|
217
|
+
uid: The index's unique identifier.
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
|
|
221
|
+
True if an index was deleted for False if not.
|
|
222
|
+
|
|
223
|
+
Raises:
|
|
224
|
+
|
|
225
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
226
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
|
|
230
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
231
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
232
|
+
>>> await client.delete_index_if_exists()
|
|
233
|
+
"""
|
|
234
|
+
response = await self._http_requests.delete(f"indexes/{uid}")
|
|
235
|
+
status = await self.wait_for_task(response.json()["taskUid"], timeout_in_ms=100000)
|
|
236
|
+
if status.status == "succeeded":
|
|
237
|
+
return True
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
async def get_indexes(
|
|
241
|
+
self, *, offset: int | None = None, limit: int | None = None
|
|
242
|
+
) -> list[AsyncIndex] | None:
|
|
243
|
+
"""Get all indexes.
|
|
244
|
+
Args:
|
|
245
|
+
|
|
246
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
247
|
+
default.
|
|
248
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
249
|
+
default.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
|
|
253
|
+
A list of all indexes.
|
|
254
|
+
|
|
255
|
+
Raises:
|
|
256
|
+
|
|
257
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
258
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
259
|
+
|
|
260
|
+
Examples:
|
|
261
|
+
|
|
262
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
263
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
264
|
+
>>> indexes = await client.get_indexes()
|
|
265
|
+
"""
|
|
266
|
+
url = _build_offset_limit_url("indexes", offset, limit)
|
|
267
|
+
response = await self._http_requests.get(url)
|
|
268
|
+
|
|
269
|
+
if not response.json()["results"]:
|
|
270
|
+
return None
|
|
271
|
+
|
|
272
|
+
return [
|
|
273
|
+
AsyncIndex(
|
|
274
|
+
http_client=self.http_client,
|
|
275
|
+
uid=x["uid"],
|
|
276
|
+
primary_key=x["primaryKey"],
|
|
277
|
+
created_at=x["createdAt"],
|
|
278
|
+
updated_at=x["updatedAt"],
|
|
279
|
+
)
|
|
280
|
+
for x in response.json()["results"]
|
|
281
|
+
]
|
|
282
|
+
|
|
283
|
+
async def get_index(self, uid: str) -> AsyncIndex:
|
|
284
|
+
"""Gets a single index based on the uid of the index.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
|
|
288
|
+
uid: The index's unique identifier.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
|
|
292
|
+
An AsyncIndex instance containing the information of the fetched index.
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
|
|
296
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
297
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
298
|
+
|
|
299
|
+
Examples:
|
|
300
|
+
|
|
301
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
302
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
303
|
+
>>> index = await client.get_index()
|
|
304
|
+
"""
|
|
305
|
+
return await AsyncIndex(self.http_client, uid).fetch_info()
|
|
306
|
+
|
|
307
|
+
def index(self, uid: str) -> AsyncIndex:
|
|
308
|
+
"""Create a local reference to an index identified by UID, without making an HTTP call.
|
|
309
|
+
|
|
310
|
+
Because no network call is made this method is not awaitable.
|
|
311
|
+
|
|
312
|
+
Args:
|
|
313
|
+
|
|
314
|
+
uid: The index's unique identifier.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
|
|
318
|
+
An AsyncIndex instance.
|
|
319
|
+
|
|
320
|
+
Raises:
|
|
321
|
+
|
|
322
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
323
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
324
|
+
|
|
325
|
+
Examples:
|
|
326
|
+
|
|
327
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
328
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
329
|
+
>>> index = client.index("movies")
|
|
330
|
+
"""
|
|
331
|
+
return AsyncIndex(self.http_client, uid=uid)
|
|
332
|
+
|
|
333
|
+
async def get_all_stats(self) -> ClientStats:
|
|
334
|
+
"""Get stats for all indexes.
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
|
|
338
|
+
Information about database size and all indexes.
|
|
339
|
+
https://docs.meilisearch.com/reference/api/stats.html
|
|
340
|
+
|
|
341
|
+
Raises:
|
|
342
|
+
|
|
343
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
344
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
345
|
+
|
|
346
|
+
Examples:
|
|
347
|
+
|
|
348
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
349
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
350
|
+
>>> stats = await client.get_all_stats()
|
|
351
|
+
"""
|
|
352
|
+
response = await self._http_requests.get("stats")
|
|
353
|
+
|
|
354
|
+
return ClientStats(**response.json())
|
|
355
|
+
|
|
356
|
+
async def get_or_create_index(self, uid: str, primary_key: str | None = None) -> AsyncIndex:
|
|
357
|
+
"""Get an index, or create it if it doesn't exist.
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
|
|
361
|
+
uid: The index's unique identifier.
|
|
362
|
+
primary_key: The primary key of the documents. Defaults to None.
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
|
|
366
|
+
An instance of AsyncIndex containing the information of the retrieved or newly created index.
|
|
367
|
+
|
|
368
|
+
Raises:
|
|
369
|
+
|
|
370
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
371
|
+
MeilisearchApiError: If the Meilisearch API returned an error.MeilisearchTimeoutError: If the connection times out.
|
|
372
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
373
|
+
|
|
374
|
+
Examples:
|
|
375
|
+
|
|
376
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
377
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
378
|
+
>>> index = await client.get_or_create_index("movies")
|
|
379
|
+
"""
|
|
380
|
+
try:
|
|
381
|
+
index_instance = await self.get_index(uid)
|
|
382
|
+
except MeilisearchApiError as err:
|
|
383
|
+
if "index_not_found" not in err.code:
|
|
384
|
+
raise
|
|
385
|
+
index_instance = await self.create_index(uid, primary_key)
|
|
386
|
+
return index_instance
|
|
387
|
+
|
|
388
|
+
async def create_key(self, key: KeyCreate) -> Key:
|
|
389
|
+
"""Creates a new API key.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
|
|
393
|
+
key: The information to use in creating the key. Note that if an expires_at value
|
|
394
|
+
is included it should be in UTC time.
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
|
|
398
|
+
The new API key.
|
|
399
|
+
|
|
400
|
+
Raises:
|
|
401
|
+
|
|
402
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
403
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
404
|
+
|
|
405
|
+
Examples:
|
|
406
|
+
|
|
407
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
408
|
+
>>> from meilissearch_async_client.models.client import KeyCreate
|
|
409
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
410
|
+
>>> key_info = KeyCreate(
|
|
411
|
+
>>> description="My new key",
|
|
412
|
+
>>> actions=["search"],
|
|
413
|
+
>>> indexes=["movies"],
|
|
414
|
+
>>> )
|
|
415
|
+
>>> keys = await client.create_key(key_info)
|
|
416
|
+
"""
|
|
417
|
+
if is_pydantic_2():
|
|
418
|
+
response = await self._http_requests.post("keys", json.loads(key.model_dump_json(by_alias=True))) # type: ignore[attr-defined]
|
|
419
|
+
else: # pragma: no cover
|
|
420
|
+
response = await self._http_requests.post("keys", json.loads(key.json(by_alias=True))) # type: ignore[attr-defined]
|
|
421
|
+
|
|
422
|
+
return Key(**response.json())
|
|
423
|
+
|
|
424
|
+
async def delete_key(self, key: str) -> int:
|
|
425
|
+
"""Deletes an API key.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
|
|
429
|
+
key: The key or uid to delete.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
|
|
433
|
+
The Response status code. 204 signifies a successful delete.
|
|
434
|
+
|
|
435
|
+
Raises:
|
|
436
|
+
|
|
437
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
438
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
439
|
+
|
|
440
|
+
Examples:
|
|
441
|
+
|
|
442
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
443
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
444
|
+
>>> await client.delete_key("abc123")
|
|
445
|
+
"""
|
|
446
|
+
response = await self._http_requests.delete(f"keys/{key}")
|
|
447
|
+
return response.status_code
|
|
448
|
+
|
|
449
|
+
async def get_keys(self, *, offset: int | None = None, limit: int | None = None) -> KeySearch:
|
|
450
|
+
"""Gets the Meilisearch API keys.
|
|
451
|
+
Args:
|
|
452
|
+
|
|
453
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
454
|
+
default.
|
|
455
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
456
|
+
default.
|
|
457
|
+
|
|
458
|
+
Returns:
|
|
459
|
+
|
|
460
|
+
API keys.
|
|
461
|
+
|
|
462
|
+
Raises:
|
|
463
|
+
|
|
464
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
465
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
466
|
+
|
|
467
|
+
Examples:
|
|
468
|
+
|
|
469
|
+
from meilisearch_python_sdk import AsyncClient
|
|
470
|
+
async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
471
|
+
keys = await client.get_keys()
|
|
472
|
+
"""
|
|
473
|
+
url = _build_offset_limit_url("keys", offset, limit)
|
|
474
|
+
response = await self._http_requests.get(url)
|
|
475
|
+
|
|
476
|
+
return KeySearch(**response.json())
|
|
477
|
+
|
|
478
|
+
async def get_key(self, key: str) -> Key:
|
|
479
|
+
"""Gets information about a specific API key.
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
|
|
483
|
+
key: The key for which to retrieve the information.
|
|
484
|
+
|
|
485
|
+
Returns:
|
|
486
|
+
|
|
487
|
+
The API key, or `None` if the key is not found.
|
|
488
|
+
|
|
489
|
+
Raises:
|
|
490
|
+
|
|
491
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
492
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
493
|
+
|
|
494
|
+
Examples:
|
|
495
|
+
|
|
496
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
497
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
498
|
+
>>> keys = await client.get_key("abc123")
|
|
499
|
+
"""
|
|
500
|
+
response = await self._http_requests.get(f"keys/{key}")
|
|
501
|
+
|
|
502
|
+
return Key(**response.json())
|
|
503
|
+
|
|
504
|
+
async def update_key(self, key: KeyUpdate) -> Key:
|
|
505
|
+
"""Update an API key.
|
|
506
|
+
|
|
507
|
+
Args:
|
|
508
|
+
|
|
509
|
+
key: The information to use in updating the key. Note that if an expires_at value
|
|
510
|
+
is included it should be in UTC time.
|
|
511
|
+
|
|
512
|
+
Returns:
|
|
513
|
+
|
|
514
|
+
The updated API key.
|
|
515
|
+
|
|
516
|
+
Raises:
|
|
517
|
+
|
|
518
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
519
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
520
|
+
|
|
521
|
+
Examples:
|
|
522
|
+
|
|
523
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
524
|
+
>>> from meilissearch_async_client.models.client import KeyUpdate
|
|
525
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
526
|
+
>>> key_info = KeyUpdate(
|
|
527
|
+
key="abc123",
|
|
528
|
+
>>> indexes=["*"],
|
|
529
|
+
>>> )
|
|
530
|
+
>>> keys = await client.update_key(key_info)
|
|
531
|
+
"""
|
|
532
|
+
payload = _build_update_key_payload(key)
|
|
533
|
+
response = await self._http_requests.patch(f"keys/{key.key}", payload)
|
|
534
|
+
|
|
535
|
+
return Key(**response.json())
|
|
536
|
+
|
|
537
|
+
async def multi_search(self, queries: list[SearchParams]) -> list[SearchResultsWithUID]:
|
|
538
|
+
"""Multi-index search.
|
|
539
|
+
|
|
540
|
+
Args:
|
|
541
|
+
|
|
542
|
+
queries: List of SearchParameters
|
|
543
|
+
|
|
544
|
+
Returns:
|
|
545
|
+
|
|
546
|
+
Results of the search
|
|
547
|
+
|
|
548
|
+
Raises:
|
|
549
|
+
|
|
550
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
551
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
552
|
+
|
|
553
|
+
Examples:
|
|
554
|
+
|
|
555
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
556
|
+
>>> from meilisearch_python_sdk.models.search import SearchParams
|
|
557
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
558
|
+
>>> queries = [
|
|
559
|
+
>>> SearchParams(index_uid="my_first_index", query"Some search"),
|
|
560
|
+
>>> SearchParams(index_uid="my_second_index", query="Another search")
|
|
561
|
+
>>> ]
|
|
562
|
+
>>> search_results = await client.search(queries)
|
|
563
|
+
"""
|
|
564
|
+
url = "multi-search"
|
|
565
|
+
if is_pydantic_2():
|
|
566
|
+
response = await self._http_requests.post(
|
|
567
|
+
url, body={"queries": [x.model_dump(by_alias=True) for x in queries]} # type: ignore[attr-defined]
|
|
568
|
+
)
|
|
569
|
+
else: # pragma: no cover
|
|
570
|
+
response = await self._http_requests.post(
|
|
571
|
+
url, body={"queries": [x.dict(by_alias=True) for x in queries]} # type: ignore[attr-defined]
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
return [SearchResultsWithUID(**x) for x in response.json()["results"]]
|
|
575
|
+
|
|
576
|
+
async def get_raw_index(self, uid: str) -> IndexInfo | None:
|
|
577
|
+
"""Gets the index and returns all the index information rather than an AsyncIndex instance.
|
|
578
|
+
|
|
579
|
+
Args:
|
|
580
|
+
|
|
581
|
+
uid: The index's unique identifier.
|
|
582
|
+
|
|
583
|
+
Returns:
|
|
584
|
+
|
|
585
|
+
Index information rather than an AsyncIndex instance.
|
|
586
|
+
|
|
587
|
+
Raises:
|
|
588
|
+
|
|
589
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
590
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
591
|
+
|
|
592
|
+
Examples:
|
|
593
|
+
|
|
594
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
595
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
596
|
+
>>> index = await client.get_raw_index("movies")
|
|
597
|
+
"""
|
|
598
|
+
response = await self.http_client.get(f"indexes/{uid}")
|
|
599
|
+
|
|
600
|
+
if response.status_code == 404:
|
|
601
|
+
return None
|
|
602
|
+
|
|
603
|
+
return IndexInfo(**response.json())
|
|
604
|
+
|
|
605
|
+
async def get_raw_indexes(
|
|
606
|
+
self, *, offset: int | None = None, limit: int | None = None
|
|
607
|
+
) -> list[IndexInfo] | None:
|
|
608
|
+
"""Gets all the indexes.
|
|
609
|
+
Args:
|
|
610
|
+
|
|
611
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
612
|
+
default.
|
|
613
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
614
|
+
default.
|
|
615
|
+
|
|
616
|
+
Returns all the index information rather than an AsyncIndex instance.
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
|
|
620
|
+
A list of the Index information rather than an AsyncIndex instances.
|
|
621
|
+
|
|
622
|
+
Raises:
|
|
623
|
+
|
|
624
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
625
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
626
|
+
|
|
627
|
+
Examples:
|
|
628
|
+
|
|
629
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
630
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
631
|
+
>>> index = await client.get_raw_indexes()
|
|
632
|
+
"""
|
|
633
|
+
url = _build_offset_limit_url("indexes", offset, limit)
|
|
634
|
+
response = await self._http_requests.get(url)
|
|
635
|
+
|
|
636
|
+
if not response.json()["results"]:
|
|
637
|
+
return None
|
|
638
|
+
|
|
639
|
+
return [IndexInfo(**x) for x in response.json()["results"]]
|
|
640
|
+
|
|
641
|
+
async def get_version(self) -> Version:
|
|
642
|
+
"""Get the Meilisearch version.
|
|
643
|
+
|
|
644
|
+
Returns:
|
|
645
|
+
|
|
646
|
+
Information about the version of Meilisearch.
|
|
647
|
+
|
|
648
|
+
Raises:
|
|
649
|
+
|
|
650
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
651
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
652
|
+
|
|
653
|
+
Examples:
|
|
654
|
+
|
|
655
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
656
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
657
|
+
>>> version = await client.get_version()
|
|
658
|
+
"""
|
|
659
|
+
response = await self._http_requests.get("version")
|
|
660
|
+
|
|
661
|
+
return Version(**response.json())
|
|
662
|
+
|
|
663
|
+
async def health(self) -> Health:
|
|
664
|
+
"""Get health of the Meilisearch server.
|
|
665
|
+
|
|
666
|
+
Returns:
|
|
667
|
+
|
|
668
|
+
The status of the Meilisearch server.
|
|
669
|
+
|
|
670
|
+
Raises:
|
|
671
|
+
|
|
672
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
673
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
674
|
+
|
|
675
|
+
Examples:
|
|
676
|
+
|
|
677
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
678
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
679
|
+
>>> health = await client.get_healths()
|
|
680
|
+
"""
|
|
681
|
+
response = await self._http_requests.get("health")
|
|
682
|
+
|
|
683
|
+
return Health(**response.json())
|
|
684
|
+
|
|
685
|
+
async def swap_indexes(self, indexes: list[tuple[str, str]]) -> TaskInfo:
|
|
686
|
+
"""Swap two indexes.
|
|
687
|
+
|
|
688
|
+
Args:
|
|
689
|
+
|
|
690
|
+
indexes: A list of tuples, each tuple should contain the indexes to swap.
|
|
691
|
+
|
|
692
|
+
Returns:
|
|
693
|
+
|
|
694
|
+
The details of the task.
|
|
695
|
+
|
|
696
|
+
Raises:
|
|
697
|
+
|
|
698
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
699
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
700
|
+
|
|
701
|
+
Examples:
|
|
702
|
+
|
|
703
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
704
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
705
|
+
>>> index = await client.swap_indexes([("index_a", "index_b")])
|
|
706
|
+
"""
|
|
707
|
+
processed_indexes = [{"indexes": x} for x in indexes]
|
|
708
|
+
response = await self._http_requests.post("swap-indexes", processed_indexes)
|
|
709
|
+
|
|
710
|
+
return TaskInfo(**response.json())
|
|
711
|
+
|
|
712
|
+
async def cancel_tasks(
|
|
713
|
+
self,
|
|
714
|
+
*,
|
|
715
|
+
uids: list[str] | None = None,
|
|
716
|
+
index_uids: list[str] | None = None,
|
|
717
|
+
statuses: list[str] | None = None,
|
|
718
|
+
types: list[str] | None = None,
|
|
719
|
+
before_enqueued_at: datetime | None = None,
|
|
720
|
+
after_enqueued_at: datetime | None = None,
|
|
721
|
+
before_started_at: datetime | None = None,
|
|
722
|
+
after_finished_at: datetime | None = None,
|
|
723
|
+
) -> TaskInfo:
|
|
724
|
+
"""Cancel a list of enqueued or processing tasks.
|
|
725
|
+
|
|
726
|
+
Defaults to cancelling all tasks.
|
|
727
|
+
|
|
728
|
+
Args:
|
|
729
|
+
|
|
730
|
+
uids: A list of task UIDs to cancel.
|
|
731
|
+
index_uids: A list of index UIDs for which to cancel tasks.
|
|
732
|
+
statuses: A list of statuses to cancel.
|
|
733
|
+
types: A list of types to cancel.
|
|
734
|
+
before_enqueued_at: Cancel tasks that were enqueued before the specified date time.
|
|
735
|
+
after_enqueued_at: Cancel tasks that were enqueued after the specified date time.
|
|
736
|
+
before_started_at: Cancel tasks that were started before the specified date time.
|
|
737
|
+
after_finished_at: Cancel tasks that were finished after the specified date time.
|
|
738
|
+
|
|
739
|
+
Returns:
|
|
740
|
+
|
|
741
|
+
The details of the task
|
|
742
|
+
|
|
743
|
+
Raises:
|
|
744
|
+
|
|
745
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
746
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
747
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
748
|
+
|
|
749
|
+
Examples:
|
|
750
|
+
|
|
751
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
752
|
+
>>>
|
|
753
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
754
|
+
>>> await client.cancel_tasks(uids=[1, 2])
|
|
755
|
+
"""
|
|
756
|
+
return await _task.async_cancel_tasks(
|
|
757
|
+
self.http_client,
|
|
758
|
+
uids=uids,
|
|
759
|
+
index_uids=index_uids,
|
|
760
|
+
statuses=statuses,
|
|
761
|
+
types=types,
|
|
762
|
+
before_enqueued_at=before_enqueued_at,
|
|
763
|
+
after_enqueued_at=after_enqueued_at,
|
|
764
|
+
before_started_at=before_started_at,
|
|
765
|
+
after_finished_at=after_finished_at,
|
|
766
|
+
)
|
|
767
|
+
|
|
768
|
+
async def get_task(self, task_id: int) -> TaskResult:
|
|
769
|
+
"""Get a single task from it's task id.
|
|
770
|
+
|
|
771
|
+
Args:
|
|
772
|
+
|
|
773
|
+
task_id: Identifier of the task to retrieve.
|
|
774
|
+
|
|
775
|
+
Returns:
|
|
776
|
+
|
|
777
|
+
Results of a task.
|
|
778
|
+
|
|
779
|
+
Raises:
|
|
780
|
+
|
|
781
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
782
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
783
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
784
|
+
|
|
785
|
+
Examples:
|
|
786
|
+
|
|
787
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
788
|
+
>>> from meilisearch_python_sdk.task import get_task
|
|
789
|
+
>>>
|
|
790
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
791
|
+
>>> await client.get_task(client, 1244)
|
|
792
|
+
"""
|
|
793
|
+
return await _task.async_get_task(self.http_client, task_id=task_id)
|
|
794
|
+
|
|
795
|
+
async def delete_tasks(
|
|
796
|
+
self,
|
|
797
|
+
*,
|
|
798
|
+
uids: list[str] | None = None,
|
|
799
|
+
index_uids: list[str] | None = None,
|
|
800
|
+
statuses: list[str] | None = None,
|
|
801
|
+
types: list[str] | None = None,
|
|
802
|
+
before_enqueued_at: datetime | None = None,
|
|
803
|
+
after_enqueued_at: datetime | None = None,
|
|
804
|
+
before_started_at: datetime | None = None,
|
|
805
|
+
after_finished_at: datetime | None = None,
|
|
806
|
+
) -> TaskInfo:
|
|
807
|
+
"""Delete a list of tasks.
|
|
808
|
+
|
|
809
|
+
Defaults to deleting all tasks.
|
|
810
|
+
|
|
811
|
+
Args:
|
|
812
|
+
|
|
813
|
+
uids: A list of task UIDs to cancel.
|
|
814
|
+
index_uids: A list of index UIDs for which to cancel tasks.
|
|
815
|
+
statuses: A list of statuses to cancel.
|
|
816
|
+
types: A list of types to cancel.
|
|
817
|
+
before_enqueued_at: Cancel tasks that were enqueued before the specified date time.
|
|
818
|
+
after_enqueued_at: Cancel tasks that were enqueued after the specified date time.
|
|
819
|
+
before_started_at: Cancel tasks that were started before the specified date time.
|
|
820
|
+
after_finished_at: Cancel tasks that were finished after the specified date time.
|
|
821
|
+
|
|
822
|
+
Returns:
|
|
823
|
+
|
|
824
|
+
The details of the task
|
|
825
|
+
|
|
826
|
+
Raises:
|
|
827
|
+
|
|
828
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
829
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
830
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
831
|
+
|
|
832
|
+
Examples:
|
|
833
|
+
|
|
834
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
835
|
+
>>> from meilisearch_python_sdk.task import delete_tasks
|
|
836
|
+
>>>
|
|
837
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
838
|
+
>>> await client.delete_tasks(uids=[1, 2])
|
|
839
|
+
"""
|
|
840
|
+
return await _task.async_delete_tasks(
|
|
841
|
+
self.http_client,
|
|
842
|
+
uids=uids,
|
|
843
|
+
index_uids=index_uids,
|
|
844
|
+
statuses=statuses,
|
|
845
|
+
types=types,
|
|
846
|
+
before_enqueued_at=before_enqueued_at,
|
|
847
|
+
after_enqueued_at=after_enqueued_at,
|
|
848
|
+
before_started_at=before_started_at,
|
|
849
|
+
after_finished_at=after_finished_at,
|
|
850
|
+
)
|
|
851
|
+
|
|
852
|
+
async def get_tasks(
|
|
853
|
+
self,
|
|
854
|
+
*,
|
|
855
|
+
index_ids: list[str] | None = None,
|
|
856
|
+
types: str | list[str] | None = None,
|
|
857
|
+
) -> TaskStatus:
|
|
858
|
+
"""Get multiple tasks.
|
|
859
|
+
|
|
860
|
+
Args:
|
|
861
|
+
|
|
862
|
+
index_ids: A list of index UIDs for which to get the tasks. If provided this will get the
|
|
863
|
+
tasks only for the specified indexes, if not all tasks will be returned. Default = None
|
|
864
|
+
types: Specify specific task types to retrieve. Default = None
|
|
865
|
+
|
|
866
|
+
Returns:
|
|
867
|
+
|
|
868
|
+
Task statuses.
|
|
869
|
+
|
|
870
|
+
Raises:
|
|
871
|
+
|
|
872
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
873
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
874
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
875
|
+
|
|
876
|
+
Examples:
|
|
877
|
+
|
|
878
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
879
|
+
>>>
|
|
880
|
+
>>> async with AsyncClient("http://localhost.com", "masterKey") as client:
|
|
881
|
+
>>> await client.get_tasks()
|
|
882
|
+
"""
|
|
883
|
+
return await _task.async_get_tasks(self.http_client, index_ids=index_ids, types=types)
|
|
884
|
+
|
|
885
|
+
async def wait_for_task(
|
|
886
|
+
self,
|
|
887
|
+
task_id: int,
|
|
888
|
+
*,
|
|
889
|
+
timeout_in_ms: int | None = 5000,
|
|
890
|
+
interval_in_ms: int = 50,
|
|
891
|
+
raise_for_status: bool = False,
|
|
892
|
+
) -> TaskResult:
|
|
893
|
+
"""Wait until Meilisearch processes a task, and get its status.
|
|
894
|
+
|
|
895
|
+
Args:
|
|
896
|
+
|
|
897
|
+
task_id: Identifier of the task to retrieve.
|
|
898
|
+
timeout_in_ms: Amount of time in milliseconds to wait before raising a
|
|
899
|
+
MeilisearchTimeoutError. `None` can also be passed to wait indefinitely. Be aware that
|
|
900
|
+
if the `None` option is used the wait time could be very long. Defaults to 5000.
|
|
901
|
+
interval_in_ms: Time interval in miliseconds to sleep between requests. Defaults to 50.
|
|
902
|
+
raise_for_status: When set to `True` a MeilisearchTaskFailedError will be raised if a task
|
|
903
|
+
has a failed status. Defaults to False.
|
|
904
|
+
|
|
905
|
+
Returns:
|
|
906
|
+
|
|
907
|
+
Details of the processed update status.
|
|
908
|
+
|
|
909
|
+
Raises:
|
|
910
|
+
|
|
911
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
912
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
913
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
914
|
+
MeilisearchTaskFailedError: If `raise_for_status` is `True` and a task has a failed status.
|
|
915
|
+
|
|
916
|
+
Examples:
|
|
917
|
+
|
|
918
|
+
>>> from meilisearch_python_sdk import AsyncClient
|
|
919
|
+
>>> >>> documents = [
|
|
920
|
+
>>> {"id": 1, "title": "Movie 1", "genre": "comedy"},
|
|
921
|
+
>>> {"id": 2, "title": "Movie 2", "genre": "drama"},
|
|
922
|
+
>>> ]
|
|
923
|
+
>>> async with Client("http://localhost.com", "masterKey") as client:
|
|
924
|
+
>>> index = client.index("movies")
|
|
925
|
+
>>> response = await index.add_documents(documents)
|
|
926
|
+
>>> await client.wait_for_task(client, response.update_id)
|
|
927
|
+
"""
|
|
928
|
+
return await _task.async_wait_for_task(
|
|
929
|
+
self.http_client,
|
|
930
|
+
task_id=task_id,
|
|
931
|
+
timeout_in_ms=timeout_in_ms,
|
|
932
|
+
interval_in_ms=interval_in_ms,
|
|
933
|
+
raise_for_status=raise_for_status,
|
|
934
|
+
)
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
class Client(BaseClient):
|
|
938
|
+
"""client to connect to the Meilisearch API."""
|
|
939
|
+
|
|
940
|
+
def __init__(
|
|
941
|
+
self,
|
|
942
|
+
url: str,
|
|
943
|
+
api_key: str | None = None,
|
|
944
|
+
*,
|
|
945
|
+
timeout: int | None = None,
|
|
946
|
+
verify: str | bool | SSLContext = True,
|
|
947
|
+
) -> None:
|
|
948
|
+
"""Class initializer.
|
|
949
|
+
|
|
950
|
+
Args:
|
|
951
|
+
|
|
952
|
+
url: The url to the Meilisearch API (ex: http://localhost:7700)
|
|
953
|
+
api_key: The optional API key for Meilisearch. Defaults to None.
|
|
954
|
+
timeout: The amount of time in seconds that the client will wait for a response before
|
|
955
|
+
timing out. Defaults to None.
|
|
956
|
+
verify: SSL certificates (a.k.a CA bundle) used to
|
|
957
|
+
verify the identity of requested hosts. Either `True` (default CA bundle),
|
|
958
|
+
a path to an SSL certificate file, or `False` (disable verification)
|
|
959
|
+
"""
|
|
960
|
+
super().__init__(api_key)
|
|
961
|
+
|
|
962
|
+
self.http_client = HttpxClient(
|
|
963
|
+
base_url=url, timeout=timeout, headers=self._headers, verify=verify
|
|
964
|
+
)
|
|
965
|
+
self._http_requests = HttpRequests(self.http_client)
|
|
966
|
+
|
|
967
|
+
def create_dump(self) -> TaskInfo:
|
|
968
|
+
"""Trigger the creation of a Meilisearch dump.
|
|
969
|
+
|
|
970
|
+
Returns:
|
|
971
|
+
|
|
972
|
+
The details of the task.
|
|
973
|
+
|
|
974
|
+
Raises:
|
|
975
|
+
|
|
976
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
977
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
978
|
+
|
|
979
|
+
Examples:
|
|
980
|
+
|
|
981
|
+
>>> from meilisearch_python_sdk import Client
|
|
982
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
983
|
+
>>> client.create_dump()
|
|
984
|
+
"""
|
|
985
|
+
response = self._http_requests.post("dumps")
|
|
986
|
+
|
|
987
|
+
return TaskInfo(**response.json())
|
|
988
|
+
|
|
989
|
+
def create_index(self, uid: str, primary_key: str | None = None) -> Index:
|
|
990
|
+
"""Creates a new index.
|
|
991
|
+
|
|
992
|
+
Args:
|
|
993
|
+
|
|
994
|
+
uid: The index's unique identifier.
|
|
995
|
+
primary_key: The primary key of the documents. Defaults to None.
|
|
996
|
+
|
|
997
|
+
Returns:
|
|
998
|
+
|
|
999
|
+
An instance of Index containing the information of the newly created index.
|
|
1000
|
+
|
|
1001
|
+
Raises:
|
|
1002
|
+
|
|
1003
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1004
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1005
|
+
|
|
1006
|
+
Examples:
|
|
1007
|
+
|
|
1008
|
+
>>> from meilisearch_python_sdk import Client
|
|
1009
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1010
|
+
>>> index = client.create_index("movies")
|
|
1011
|
+
"""
|
|
1012
|
+
return Index.create(self.http_client, uid, primary_key)
|
|
1013
|
+
|
|
1014
|
+
def delete_index_if_exists(self, uid: str) -> bool:
|
|
1015
|
+
"""Deletes an index if it already exists.
|
|
1016
|
+
|
|
1017
|
+
Args:
|
|
1018
|
+
|
|
1019
|
+
uid: The index's unique identifier.
|
|
1020
|
+
|
|
1021
|
+
Returns:
|
|
1022
|
+
|
|
1023
|
+
True if an index was deleted for False if not.
|
|
1024
|
+
|
|
1025
|
+
Raises:
|
|
1026
|
+
|
|
1027
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1028
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1029
|
+
|
|
1030
|
+
Examples:
|
|
1031
|
+
|
|
1032
|
+
>>> from meilisearch_python_sdk import Client
|
|
1033
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1034
|
+
>>> client.delete_index_if_exists()
|
|
1035
|
+
"""
|
|
1036
|
+
response = self._http_requests.delete(f"indexes/{uid}")
|
|
1037
|
+
status = self.wait_for_task(response.json()["taskUid"], timeout_in_ms=100000)
|
|
1038
|
+
if status.status == "succeeded":
|
|
1039
|
+
return True
|
|
1040
|
+
return False
|
|
1041
|
+
|
|
1042
|
+
def get_indexes(
|
|
1043
|
+
self, *, offset: int | None = None, limit: int | None = None
|
|
1044
|
+
) -> list[Index] | None:
|
|
1045
|
+
"""Get all indexes.
|
|
1046
|
+
Args:
|
|
1047
|
+
|
|
1048
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
1049
|
+
default.
|
|
1050
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
1051
|
+
default.
|
|
1052
|
+
|
|
1053
|
+
Returns:
|
|
1054
|
+
|
|
1055
|
+
A list of all indexes.
|
|
1056
|
+
|
|
1057
|
+
Raises:
|
|
1058
|
+
|
|
1059
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1060
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1061
|
+
|
|
1062
|
+
Examples:
|
|
1063
|
+
|
|
1064
|
+
>>> from meilisearch_python_sdk import Client
|
|
1065
|
+
>>> client = Client("http://localhost.com", "masterKey") as client:
|
|
1066
|
+
>>> indexes = client.get_indexes()
|
|
1067
|
+
"""
|
|
1068
|
+
url = _build_offset_limit_url("indexes", offset, limit)
|
|
1069
|
+
response = self._http_requests.get(url)
|
|
1070
|
+
|
|
1071
|
+
if not response.json()["results"]:
|
|
1072
|
+
return None
|
|
1073
|
+
|
|
1074
|
+
return [
|
|
1075
|
+
Index(
|
|
1076
|
+
http_client=self.http_client,
|
|
1077
|
+
uid=x["uid"],
|
|
1078
|
+
primary_key=x["primaryKey"],
|
|
1079
|
+
created_at=x["createdAt"],
|
|
1080
|
+
updated_at=x["updatedAt"],
|
|
1081
|
+
)
|
|
1082
|
+
for x in response.json()["results"]
|
|
1083
|
+
]
|
|
1084
|
+
|
|
1085
|
+
def get_index(self, uid: str) -> Index:
|
|
1086
|
+
"""Gets a single index based on the uid of the index.
|
|
1087
|
+
|
|
1088
|
+
Args:
|
|
1089
|
+
|
|
1090
|
+
uid: The index's unique identifier.
|
|
1091
|
+
|
|
1092
|
+
Returns:
|
|
1093
|
+
|
|
1094
|
+
An Index instance containing the information of the fetched index.
|
|
1095
|
+
|
|
1096
|
+
Raises:
|
|
1097
|
+
|
|
1098
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1099
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1100
|
+
|
|
1101
|
+
Examples:
|
|
1102
|
+
|
|
1103
|
+
>>> from meilisearch_python_sdk import Client
|
|
1104
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1105
|
+
>>> index = client.get_index()
|
|
1106
|
+
"""
|
|
1107
|
+
return Index(self.http_client, uid).fetch_info()
|
|
1108
|
+
|
|
1109
|
+
def index(self, uid: str) -> Index:
|
|
1110
|
+
"""Create a local reference to an index identified by UID, without making an HTTP call.
|
|
1111
|
+
|
|
1112
|
+
Args:
|
|
1113
|
+
|
|
1114
|
+
uid: The index's unique identifier.
|
|
1115
|
+
|
|
1116
|
+
Returns:
|
|
1117
|
+
|
|
1118
|
+
An Index instance.
|
|
1119
|
+
|
|
1120
|
+
Raises:
|
|
1121
|
+
|
|
1122
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1123
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1124
|
+
|
|
1125
|
+
Examples:
|
|
1126
|
+
|
|
1127
|
+
>>> from meilisearch_python_sdk import Client
|
|
1128
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1129
|
+
>>> index = client.index("movies")
|
|
1130
|
+
"""
|
|
1131
|
+
return Index(self.http_client, uid=uid)
|
|
1132
|
+
|
|
1133
|
+
def get_all_stats(self) -> ClientStats:
|
|
1134
|
+
"""Get stats for all indexes.
|
|
1135
|
+
|
|
1136
|
+
Returns:
|
|
1137
|
+
|
|
1138
|
+
Information about database size and all indexes.
|
|
1139
|
+
https://docs.meilisearch.com/reference/api/stats.html
|
|
1140
|
+
|
|
1141
|
+
Raises:
|
|
1142
|
+
|
|
1143
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1144
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1145
|
+
|
|
1146
|
+
Examples:
|
|
1147
|
+
|
|
1148
|
+
>>> from meilisearch_python_sdk import Client
|
|
1149
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1150
|
+
>>> stats = client.get_all_stats()
|
|
1151
|
+
"""
|
|
1152
|
+
response = self._http_requests.get("stats")
|
|
1153
|
+
|
|
1154
|
+
return ClientStats(**response.json())
|
|
1155
|
+
|
|
1156
|
+
def get_or_create_index(self, uid: str, primary_key: str | None = None) -> Index:
|
|
1157
|
+
"""Get an index, or create it if it doesn't exist.
|
|
1158
|
+
|
|
1159
|
+
Args:
|
|
1160
|
+
|
|
1161
|
+
uid: The index's unique identifier.
|
|
1162
|
+
primary_key: The primary key of the documents. Defaults to None.
|
|
1163
|
+
|
|
1164
|
+
Returns:
|
|
1165
|
+
|
|
1166
|
+
An instance of Index containing the information of the retrieved or newly created index.
|
|
1167
|
+
|
|
1168
|
+
Raises:
|
|
1169
|
+
|
|
1170
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1171
|
+
MeilisearchApiError: If the Meilisearch API returned an error.MeilisearchTimeoutError: If the connection times out.
|
|
1172
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1173
|
+
|
|
1174
|
+
Examples:
|
|
1175
|
+
|
|
1176
|
+
>>> from meilisearch_python_sdk import Client
|
|
1177
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1178
|
+
>>> index = client.get_or_create_index("movies")
|
|
1179
|
+
"""
|
|
1180
|
+
try:
|
|
1181
|
+
index_instance = self.get_index(uid)
|
|
1182
|
+
except MeilisearchApiError as err:
|
|
1183
|
+
if "index_not_found" not in err.code:
|
|
1184
|
+
raise
|
|
1185
|
+
index_instance = self.create_index(uid, primary_key)
|
|
1186
|
+
return index_instance
|
|
1187
|
+
|
|
1188
|
+
def create_key(self, key: KeyCreate) -> Key:
|
|
1189
|
+
"""Creates a new API key.
|
|
1190
|
+
|
|
1191
|
+
Args:
|
|
1192
|
+
|
|
1193
|
+
key: The information to use in creating the key. Note that if an expires_at value
|
|
1194
|
+
is included it should be in UTC time.
|
|
1195
|
+
|
|
1196
|
+
Returns:
|
|
1197
|
+
|
|
1198
|
+
The new API key.
|
|
1199
|
+
|
|
1200
|
+
Raises:
|
|
1201
|
+
|
|
1202
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1203
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1204
|
+
|
|
1205
|
+
Examples:
|
|
1206
|
+
|
|
1207
|
+
>>> from meilisearch_python_sdk import Client
|
|
1208
|
+
>>> from meilissearch_async_client.models.client import KeyCreate
|
|
1209
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1210
|
+
>>> key_info = KeyCreate(
|
|
1211
|
+
>>> description="My new key",
|
|
1212
|
+
>>> actions=["search"],
|
|
1213
|
+
>>> indexes=["movies"],
|
|
1214
|
+
>>> )
|
|
1215
|
+
>>> keys = client.create_key(key_info)
|
|
1216
|
+
"""
|
|
1217
|
+
if is_pydantic_2():
|
|
1218
|
+
response = self._http_requests.post("keys", json.loads(key.model_dump_json(by_alias=True))) # type: ignore[attr-defined]
|
|
1219
|
+
else: # pragma: no cover
|
|
1220
|
+
response = self._http_requests.post("keys", json.loads(key.json(by_alias=True))) # type: ignore[attr-defined]
|
|
1221
|
+
|
|
1222
|
+
return Key(**response.json())
|
|
1223
|
+
|
|
1224
|
+
def delete_key(self, key: str) -> int:
|
|
1225
|
+
"""Deletes an API key.
|
|
1226
|
+
|
|
1227
|
+
Args:
|
|
1228
|
+
|
|
1229
|
+
key: The key or uid to delete.
|
|
1230
|
+
|
|
1231
|
+
Returns:
|
|
1232
|
+
|
|
1233
|
+
The Response status code. 204 signifies a successful delete.
|
|
1234
|
+
|
|
1235
|
+
Raises:
|
|
1236
|
+
|
|
1237
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1238
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1239
|
+
|
|
1240
|
+
Examples:
|
|
1241
|
+
|
|
1242
|
+
>>> from meilisearch_python_sdk import Client
|
|
1243
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1244
|
+
>>> client.delete_key("abc123")
|
|
1245
|
+
"""
|
|
1246
|
+
response = self._http_requests.delete(f"keys/{key}")
|
|
1247
|
+
return response.status_code
|
|
1248
|
+
|
|
1249
|
+
def get_keys(self, *, offset: int | None = None, limit: int | None = None) -> KeySearch:
|
|
1250
|
+
"""Gets the Meilisearch API keys.
|
|
1251
|
+
Args:
|
|
1252
|
+
|
|
1253
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
1254
|
+
default.
|
|
1255
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
1256
|
+
default.
|
|
1257
|
+
|
|
1258
|
+
Returns:
|
|
1259
|
+
|
|
1260
|
+
API keys.
|
|
1261
|
+
|
|
1262
|
+
Raises:
|
|
1263
|
+
|
|
1264
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1265
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1266
|
+
|
|
1267
|
+
Examples:
|
|
1268
|
+
|
|
1269
|
+
>>> from meilisearch_python_sdk import Client
|
|
1270
|
+
>>> client = AsyncClient("http://localhost.com", "masterKey")
|
|
1271
|
+
>>> keys = client.get_keys()
|
|
1272
|
+
"""
|
|
1273
|
+
url = _build_offset_limit_url("keys", offset, limit)
|
|
1274
|
+
response = self._http_requests.get(url)
|
|
1275
|
+
|
|
1276
|
+
return KeySearch(**response.json())
|
|
1277
|
+
|
|
1278
|
+
def get_key(self, key: str) -> Key:
|
|
1279
|
+
"""Gets information about a specific API key.
|
|
1280
|
+
|
|
1281
|
+
Args:
|
|
1282
|
+
|
|
1283
|
+
key: The key for which to retrieve the information.
|
|
1284
|
+
|
|
1285
|
+
Returns:
|
|
1286
|
+
|
|
1287
|
+
The API key, or `None` if the key is not found.
|
|
1288
|
+
|
|
1289
|
+
Raises:
|
|
1290
|
+
|
|
1291
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1292
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1293
|
+
|
|
1294
|
+
Examples:
|
|
1295
|
+
|
|
1296
|
+
>>> from meilisearch_python_sdk import Client
|
|
1297
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1298
|
+
>>> keys = client.get_key("abc123")
|
|
1299
|
+
"""
|
|
1300
|
+
response = self._http_requests.get(f"keys/{key}")
|
|
1301
|
+
|
|
1302
|
+
return Key(**response.json())
|
|
1303
|
+
|
|
1304
|
+
def update_key(self, key: KeyUpdate) -> Key:
|
|
1305
|
+
"""Update an API key.
|
|
1306
|
+
|
|
1307
|
+
Args:
|
|
1308
|
+
|
|
1309
|
+
key: The information to use in updating the key. Note that if an expires_at value
|
|
1310
|
+
is included it should be in UTC time.
|
|
1311
|
+
|
|
1312
|
+
Returns:
|
|
1313
|
+
|
|
1314
|
+
The updated API key.
|
|
1315
|
+
|
|
1316
|
+
Raises:
|
|
1317
|
+
|
|
1318
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1319
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1320
|
+
|
|
1321
|
+
Examples:
|
|
1322
|
+
|
|
1323
|
+
>>> from meilisearch_python_sdk import Client
|
|
1324
|
+
>>> from meilissearch_async_client.models.client import KeyUpdate
|
|
1325
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1326
|
+
>>> key_info = KeyUpdate(
|
|
1327
|
+
key="abc123",
|
|
1328
|
+
>>> indexes=["*"],
|
|
1329
|
+
>>> )
|
|
1330
|
+
>>> keys = client.update_key(key_info)
|
|
1331
|
+
"""
|
|
1332
|
+
payload = _build_update_key_payload(key)
|
|
1333
|
+
response = self._http_requests.patch(f"keys/{key.key}", payload)
|
|
1334
|
+
|
|
1335
|
+
return Key(**response.json())
|
|
1336
|
+
|
|
1337
|
+
def multi_search(self, queries: list[SearchParams]) -> list[SearchResultsWithUID]:
|
|
1338
|
+
"""Multi-index search.
|
|
1339
|
+
|
|
1340
|
+
Args:
|
|
1341
|
+
|
|
1342
|
+
queries: List of SearchParameters
|
|
1343
|
+
|
|
1344
|
+
Returns:
|
|
1345
|
+
|
|
1346
|
+
Results of the search
|
|
1347
|
+
|
|
1348
|
+
Raises:
|
|
1349
|
+
|
|
1350
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1351
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1352
|
+
|
|
1353
|
+
Examples:
|
|
1354
|
+
|
|
1355
|
+
>>> from meilisearch_python_sdk import Client
|
|
1356
|
+
>>> from meilisearch_python_sdk.models.search import SearchParams
|
|
1357
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1358
|
+
>>> queries = [
|
|
1359
|
+
>>> SearchParams(index_uid="my_first_index", query"Some search"),
|
|
1360
|
+
>>> SearchParams(index_uid="my_second_index", query="Another search")
|
|
1361
|
+
>>> ]
|
|
1362
|
+
>>> search_results = client.search(queries)
|
|
1363
|
+
"""
|
|
1364
|
+
url = "multi-search"
|
|
1365
|
+
if is_pydantic_2():
|
|
1366
|
+
response = self._http_requests.post(
|
|
1367
|
+
url, body={"queries": [x.model_dump(by_alias=True) for x in queries]} # type: ignore[attr-defined]
|
|
1368
|
+
)
|
|
1369
|
+
else: # pragma: no cover
|
|
1370
|
+
response = self._http_requests.post(
|
|
1371
|
+
url, body={"queries": [x.dict(by_alias=True) for x in queries]} # type: ignore[attr-defined]
|
|
1372
|
+
)
|
|
1373
|
+
|
|
1374
|
+
return [SearchResultsWithUID(**x) for x in response.json()["results"]]
|
|
1375
|
+
|
|
1376
|
+
def get_raw_index(self, uid: str) -> IndexInfo | None:
|
|
1377
|
+
"""Gets the index and returns all the index information rather than an Index instance.
|
|
1378
|
+
|
|
1379
|
+
Args:
|
|
1380
|
+
|
|
1381
|
+
uid: The index's unique identifier.
|
|
1382
|
+
|
|
1383
|
+
Returns:
|
|
1384
|
+
|
|
1385
|
+
Index information rather than an Index instance.
|
|
1386
|
+
|
|
1387
|
+
Raises:
|
|
1388
|
+
|
|
1389
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1390
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1391
|
+
|
|
1392
|
+
Examples:
|
|
1393
|
+
|
|
1394
|
+
>>> from meilisearch_python_sdk import Client
|
|
1395
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1396
|
+
>>> index = client.get_raw_index("movies")
|
|
1397
|
+
"""
|
|
1398
|
+
response = self.http_client.get(f"indexes/{uid}")
|
|
1399
|
+
|
|
1400
|
+
if response.status_code == 404:
|
|
1401
|
+
return None
|
|
1402
|
+
|
|
1403
|
+
return IndexInfo(**response.json())
|
|
1404
|
+
|
|
1405
|
+
def get_raw_indexes(
|
|
1406
|
+
self, *, offset: int | None = None, limit: int | None = None
|
|
1407
|
+
) -> list[IndexInfo] | None:
|
|
1408
|
+
"""Gets all the indexes.
|
|
1409
|
+
Args:
|
|
1410
|
+
|
|
1411
|
+
offset: Number of indexes to skip. The default of None will use the Meilisearch
|
|
1412
|
+
default.
|
|
1413
|
+
limit: Number of indexes to return. The default of None will use the Meilisearch
|
|
1414
|
+
default.
|
|
1415
|
+
|
|
1416
|
+
Returns all the index information rather than an AsyncIndex instance.
|
|
1417
|
+
|
|
1418
|
+
Returns:
|
|
1419
|
+
|
|
1420
|
+
A list of the Index information rather than an AsyncIndex instances.
|
|
1421
|
+
|
|
1422
|
+
Raises:
|
|
1423
|
+
|
|
1424
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1425
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1426
|
+
|
|
1427
|
+
Examples:
|
|
1428
|
+
|
|
1429
|
+
>>> from meilisearch_python_sdk import Client
|
|
1430
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1431
|
+
>>> index = client.get_raw_indexes()
|
|
1432
|
+
"""
|
|
1433
|
+
url = _build_offset_limit_url("indexes", offset, limit)
|
|
1434
|
+
response = self._http_requests.get(url)
|
|
1435
|
+
|
|
1436
|
+
if not response.json()["results"]:
|
|
1437
|
+
return None
|
|
1438
|
+
|
|
1439
|
+
return [IndexInfo(**x) for x in response.json()["results"]]
|
|
1440
|
+
|
|
1441
|
+
def get_version(self) -> Version:
|
|
1442
|
+
"""Get the Meilisearch version.
|
|
1443
|
+
|
|
1444
|
+
Returns:
|
|
1445
|
+
|
|
1446
|
+
Information about the version of Meilisearch.
|
|
1447
|
+
|
|
1448
|
+
Raises:
|
|
1449
|
+
|
|
1450
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1451
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1452
|
+
|
|
1453
|
+
Examples:
|
|
1454
|
+
|
|
1455
|
+
>>> from meilisearch_python_sdk import Client
|
|
1456
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1457
|
+
>>> version = client.get_version()
|
|
1458
|
+
"""
|
|
1459
|
+
response = self._http_requests.get("version")
|
|
1460
|
+
|
|
1461
|
+
return Version(**response.json())
|
|
1462
|
+
|
|
1463
|
+
def health(self) -> Health:
|
|
1464
|
+
"""Get health of the Meilisearch server.
|
|
1465
|
+
|
|
1466
|
+
Returns:
|
|
1467
|
+
|
|
1468
|
+
The status of the Meilisearch server.
|
|
1469
|
+
|
|
1470
|
+
Raises:
|
|
1471
|
+
|
|
1472
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1473
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1474
|
+
|
|
1475
|
+
Examples:
|
|
1476
|
+
|
|
1477
|
+
>>> from meilisearch_python_sdk import Client
|
|
1478
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1479
|
+
>>> health = client.get_healths()
|
|
1480
|
+
"""
|
|
1481
|
+
response = self._http_requests.get("health")
|
|
1482
|
+
|
|
1483
|
+
return Health(**response.json())
|
|
1484
|
+
|
|
1485
|
+
def swap_indexes(self, indexes: list[tuple[str, str]]) -> TaskInfo:
|
|
1486
|
+
"""Swap two indexes.
|
|
1487
|
+
|
|
1488
|
+
Args:
|
|
1489
|
+
|
|
1490
|
+
indexes: A list of tuples, each tuple should contain the indexes to swap.
|
|
1491
|
+
|
|
1492
|
+
Returns:
|
|
1493
|
+
|
|
1494
|
+
The details of the task.
|
|
1495
|
+
|
|
1496
|
+
Raises:
|
|
1497
|
+
|
|
1498
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1499
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1500
|
+
|
|
1501
|
+
Examples:
|
|
1502
|
+
|
|
1503
|
+
>>> from meilisearch_python_sdk import Client
|
|
1504
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1505
|
+
>>> index = client.swap_indexes([("index_a", "index_b")])
|
|
1506
|
+
"""
|
|
1507
|
+
processed_indexes = [{"indexes": x} for x in indexes]
|
|
1508
|
+
response = self._http_requests.post("swap-indexes", processed_indexes)
|
|
1509
|
+
|
|
1510
|
+
return TaskInfo(**response.json())
|
|
1511
|
+
|
|
1512
|
+
def cancel_tasks(
|
|
1513
|
+
self,
|
|
1514
|
+
*,
|
|
1515
|
+
uids: list[str] | None = None,
|
|
1516
|
+
index_uids: list[str] | None = None,
|
|
1517
|
+
statuses: list[str] | None = None,
|
|
1518
|
+
types: list[str] | None = None,
|
|
1519
|
+
before_enqueued_at: datetime | None = None,
|
|
1520
|
+
after_enqueued_at: datetime | None = None,
|
|
1521
|
+
before_started_at: datetime | None = None,
|
|
1522
|
+
after_finished_at: datetime | None = None,
|
|
1523
|
+
) -> TaskInfo:
|
|
1524
|
+
"""Cancel a list of enqueued or processing tasks.
|
|
1525
|
+
|
|
1526
|
+
Defaults to cancelling all tasks.
|
|
1527
|
+
|
|
1528
|
+
Args:
|
|
1529
|
+
|
|
1530
|
+
uids: A list of task UIDs to cancel.
|
|
1531
|
+
index_uids: A list of index UIDs for which to cancel tasks.
|
|
1532
|
+
statuses: A list of statuses to cancel.
|
|
1533
|
+
types: A list of types to cancel.
|
|
1534
|
+
before_enqueued_at: Cancel tasks that were enqueued before the specified date time.
|
|
1535
|
+
after_enqueued_at: Cancel tasks that were enqueued after the specified date time.
|
|
1536
|
+
before_started_at: Cancel tasks that were started before the specified date time.
|
|
1537
|
+
after_finished_at: Cancel tasks that were finished after the specified date time.
|
|
1538
|
+
|
|
1539
|
+
Returns:
|
|
1540
|
+
|
|
1541
|
+
The details of the task
|
|
1542
|
+
|
|
1543
|
+
Raises:
|
|
1544
|
+
|
|
1545
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1546
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1547
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1548
|
+
|
|
1549
|
+
Examples:
|
|
1550
|
+
|
|
1551
|
+
>>> from meilisearch_python_sdk import Client
|
|
1552
|
+
>>> from meilisearch_python_sdk.task import cancel_tasks
|
|
1553
|
+
>>>
|
|
1554
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1555
|
+
>>> client.cancel_tasks(uids=[1, 2])
|
|
1556
|
+
"""
|
|
1557
|
+
return _task.cancel_tasks(
|
|
1558
|
+
self.http_client,
|
|
1559
|
+
uids=uids,
|
|
1560
|
+
index_uids=index_uids,
|
|
1561
|
+
statuses=statuses,
|
|
1562
|
+
types=types,
|
|
1563
|
+
before_enqueued_at=before_enqueued_at,
|
|
1564
|
+
after_enqueued_at=after_enqueued_at,
|
|
1565
|
+
before_started_at=before_started_at,
|
|
1566
|
+
after_finished_at=after_finished_at,
|
|
1567
|
+
)
|
|
1568
|
+
|
|
1569
|
+
def delete_tasks(
|
|
1570
|
+
self,
|
|
1571
|
+
*,
|
|
1572
|
+
uids: list[str] | None = None,
|
|
1573
|
+
index_uids: list[str] | None = None,
|
|
1574
|
+
statuses: list[str] | None = None,
|
|
1575
|
+
types: list[str] | None = None,
|
|
1576
|
+
before_enqueued_at: datetime | None = None,
|
|
1577
|
+
after_enqueued_at: datetime | None = None,
|
|
1578
|
+
before_started_at: datetime | None = None,
|
|
1579
|
+
after_finished_at: datetime | None = None,
|
|
1580
|
+
) -> TaskInfo:
|
|
1581
|
+
"""Delete a list of tasks.
|
|
1582
|
+
|
|
1583
|
+
Defaults to deleting all tasks.
|
|
1584
|
+
|
|
1585
|
+
Args:
|
|
1586
|
+
|
|
1587
|
+
uids: A list of task UIDs to cancel.
|
|
1588
|
+
index_uids: A list of index UIDs for which to cancel tasks.
|
|
1589
|
+
statuses: A list of statuses to cancel.
|
|
1590
|
+
types: A list of types to cancel.
|
|
1591
|
+
before_enqueued_at: Cancel tasks that were enqueued before the specified date time.
|
|
1592
|
+
after_enqueued_at: Cancel tasks that were enqueued after the specified date time.
|
|
1593
|
+
before_started_at: Cancel tasks that were started before the specified date time.
|
|
1594
|
+
after_finished_at: Cancel tasks that were finished after the specified date time.
|
|
1595
|
+
|
|
1596
|
+
Returns:
|
|
1597
|
+
|
|
1598
|
+
The details of the task
|
|
1599
|
+
|
|
1600
|
+
Raises:
|
|
1601
|
+
|
|
1602
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1603
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1604
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1605
|
+
|
|
1606
|
+
Examples:
|
|
1607
|
+
|
|
1608
|
+
>>> from meilisearch_python_sdk import Client
|
|
1609
|
+
>>>
|
|
1610
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1611
|
+
>>> client.delete_tasks(client, uids=[1, 2])
|
|
1612
|
+
"""
|
|
1613
|
+
return _task.delete_tasks(
|
|
1614
|
+
self.http_client,
|
|
1615
|
+
uids=uids,
|
|
1616
|
+
index_uids=index_uids,
|
|
1617
|
+
statuses=statuses,
|
|
1618
|
+
types=types,
|
|
1619
|
+
before_enqueued_at=before_enqueued_at,
|
|
1620
|
+
after_enqueued_at=after_enqueued_at,
|
|
1621
|
+
before_started_at=before_started_at,
|
|
1622
|
+
after_finished_at=after_finished_at,
|
|
1623
|
+
)
|
|
1624
|
+
|
|
1625
|
+
def get_task(self, task_id: int) -> TaskResult:
|
|
1626
|
+
"""Get a single task from it's task id.
|
|
1627
|
+
|
|
1628
|
+
Args:
|
|
1629
|
+
|
|
1630
|
+
task_id: Identifier of the task to retrieve.
|
|
1631
|
+
|
|
1632
|
+
Returns:
|
|
1633
|
+
|
|
1634
|
+
Results of a task.
|
|
1635
|
+
|
|
1636
|
+
Raises:
|
|
1637
|
+
|
|
1638
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1639
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1640
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1641
|
+
|
|
1642
|
+
Examples:
|
|
1643
|
+
|
|
1644
|
+
>>> from meilisearch_python_sdk import Client
|
|
1645
|
+
>>>
|
|
1646
|
+
>>> client = AsyncClient("http://localhost.com", "masterKey")
|
|
1647
|
+
>>> get_task(client, 1244)
|
|
1648
|
+
"""
|
|
1649
|
+
return _task.get_task(self.http_client, task_id=task_id)
|
|
1650
|
+
|
|
1651
|
+
def get_tasks(
|
|
1652
|
+
self,
|
|
1653
|
+
*,
|
|
1654
|
+
index_ids: list[str] | None = None,
|
|
1655
|
+
types: str | list[str] | None = None,
|
|
1656
|
+
) -> TaskStatus:
|
|
1657
|
+
"""Get multiple tasks.
|
|
1658
|
+
|
|
1659
|
+
Args:
|
|
1660
|
+
|
|
1661
|
+
index_ids: A list of index UIDs for which to get the tasks. If provided this will get the
|
|
1662
|
+
tasks only for the specified indexes, if not all tasks will be returned. Default = None
|
|
1663
|
+
types: Specify specific task types to retrieve. Default = None
|
|
1664
|
+
|
|
1665
|
+
Returns:
|
|
1666
|
+
|
|
1667
|
+
Task statuses.
|
|
1668
|
+
|
|
1669
|
+
Raises:
|
|
1670
|
+
|
|
1671
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1672
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1673
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1674
|
+
|
|
1675
|
+
Examples:
|
|
1676
|
+
|
|
1677
|
+
>>> from meilisearch_python_sdk import Client
|
|
1678
|
+
>>>
|
|
1679
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1680
|
+
>>> client.get_tasks(client)
|
|
1681
|
+
"""
|
|
1682
|
+
return _task.get_tasks(self.http_client, index_ids=index_ids, types=types)
|
|
1683
|
+
|
|
1684
|
+
def wait_for_task(
|
|
1685
|
+
self,
|
|
1686
|
+
task_id: int,
|
|
1687
|
+
*,
|
|
1688
|
+
timeout_in_ms: int | None = 5000,
|
|
1689
|
+
interval_in_ms: int = 50,
|
|
1690
|
+
raise_for_status: bool = False,
|
|
1691
|
+
) -> TaskResult:
|
|
1692
|
+
"""Wait until Meilisearch processes a task, and get its status.
|
|
1693
|
+
|
|
1694
|
+
Args:
|
|
1695
|
+
|
|
1696
|
+
client: An httpx HttpxClient or meilisearch_python_sdk Client instance.
|
|
1697
|
+
task_id: Identifier of the task to retrieve.
|
|
1698
|
+
timeout_in_ms: Amount of time in milliseconds to wait before raising a
|
|
1699
|
+
MeilisearchTimeoutError. `None` can also be passed to wait indefinitely. Be aware that
|
|
1700
|
+
if the `None` option is used the wait time could be very long. Defaults to 5000.
|
|
1701
|
+
interval_in_ms: Time interval in miliseconds to sleep between requests. Defaults to 50.
|
|
1702
|
+
raise_for_status: When set to `True` a MeilisearchTaskFailedError will be raised if a task
|
|
1703
|
+
has a failed status. Defaults to False.
|
|
1704
|
+
|
|
1705
|
+
Returns:
|
|
1706
|
+
|
|
1707
|
+
Details of the processed update status.
|
|
1708
|
+
|
|
1709
|
+
Raises:
|
|
1710
|
+
|
|
1711
|
+
MeilisearchCommunicationError: If there was an error communicating with the server.
|
|
1712
|
+
MeilisearchApiError: If the Meilisearch API returned an error.
|
|
1713
|
+
MeilisearchTimeoutError: If the connection times out.
|
|
1714
|
+
MeilisearchTaskFailedError: If `raise_for_status` is `True` and a task has a failed status.
|
|
1715
|
+
|
|
1716
|
+
Examples:
|
|
1717
|
+
|
|
1718
|
+
>>> from meilisearch_python_sdk import Client
|
|
1719
|
+
>>> >>> documents = [
|
|
1720
|
+
>>> {"id": 1, "title": "Movie 1", "genre": "comedy"},
|
|
1721
|
+
>>> {"id": 2, "title": "Movie 2", "genre": "drama"},
|
|
1722
|
+
>>> ]
|
|
1723
|
+
>>> client = Client("http://localhost.com", "masterKey")
|
|
1724
|
+
>>> index = client.index("movies")
|
|
1725
|
+
>>> response = await index.add_documents(documents)
|
|
1726
|
+
>>> client.wait_for_task(response.update_id)
|
|
1727
|
+
"""
|
|
1728
|
+
return _task.wait_for_task(
|
|
1729
|
+
self.http_client,
|
|
1730
|
+
task_id=task_id,
|
|
1731
|
+
timeout_in_ms=timeout_in_ms,
|
|
1732
|
+
interval_in_ms=interval_in_ms,
|
|
1733
|
+
raise_for_status=raise_for_status,
|
|
1734
|
+
)
|
|
1735
|
+
|
|
1736
|
+
|
|
1737
|
+
def _build_offset_limit_url(base: str, offset: int | None, limit: int | None) -> str:
|
|
1738
|
+
if offset is not None and limit is not None:
|
|
1739
|
+
return f"{base}?offset={offset}&limit={limit}"
|
|
1740
|
+
elif offset is not None:
|
|
1741
|
+
return f"{base}?offset={offset}"
|
|
1742
|
+
elif limit is not None:
|
|
1743
|
+
return f"{base}?limit={limit}"
|
|
1744
|
+
|
|
1745
|
+
return base
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
def _build_update_key_payload(key: KeyUpdate) -> dict[str, Any]:
|
|
1749
|
+
# The json.loads(key.json()) is because Pydantic can't serialize a date in a Python dict,
|
|
1750
|
+
# but can when converting to a json string.
|
|
1751
|
+
if is_pydantic_2():
|
|
1752
|
+
return { # type: ignore[attr-defined]
|
|
1753
|
+
k: v
|
|
1754
|
+
for k, v in json.loads(key.model_dump_json(by_alias=True)).items()
|
|
1755
|
+
if v is not None and k != "key"
|
|
1756
|
+
}
|
|
1757
|
+
else: # pragma: no cover
|
|
1758
|
+
return { # type: ignore[attr-defined]
|
|
1759
|
+
k: v
|
|
1760
|
+
for k, v in json.loads(key.json(by_alias=True)).items()
|
|
1761
|
+
if v is not None and k != "key"
|
|
1762
|
+
}
|