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,67 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
import pydantic
|
|
5
|
+
from camel_converter.pydantic_base import CamelBase
|
|
6
|
+
|
|
7
|
+
from meilisearch_python_sdk._utils import is_pydantic_2, iso_to_date_time
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class IndexBase(CamelBase):
|
|
11
|
+
uid: str
|
|
12
|
+
primary_key: Optional[str]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IndexInfo(IndexBase):
|
|
16
|
+
created_at: datetime
|
|
17
|
+
updated_at: datetime
|
|
18
|
+
|
|
19
|
+
if is_pydantic_2():
|
|
20
|
+
|
|
21
|
+
@pydantic.field_validator("created_at", mode="before") # type: ignore[attr-defined]
|
|
22
|
+
@classmethod
|
|
23
|
+
def validate_created_at(cls, v: str) -> datetime:
|
|
24
|
+
converted = iso_to_date_time(v)
|
|
25
|
+
|
|
26
|
+
if not converted: # pragma: no cover
|
|
27
|
+
raise ValueError("created_at is required")
|
|
28
|
+
|
|
29
|
+
return converted
|
|
30
|
+
|
|
31
|
+
@pydantic.field_validator("updated_at", mode="before") # type: ignore[attr-defined]
|
|
32
|
+
@classmethod
|
|
33
|
+
def validate_updated_at(cls, v: str) -> datetime:
|
|
34
|
+
converted = iso_to_date_time(v)
|
|
35
|
+
|
|
36
|
+
if not converted: # pragma: no cover
|
|
37
|
+
raise ValueError("updated_at is required")
|
|
38
|
+
|
|
39
|
+
return converted
|
|
40
|
+
|
|
41
|
+
else: # pragma: no cover
|
|
42
|
+
|
|
43
|
+
@pydantic.validator("created_at", pre=True)
|
|
44
|
+
@classmethod
|
|
45
|
+
def validate_created_at(cls, v: str) -> datetime:
|
|
46
|
+
converted = iso_to_date_time(v)
|
|
47
|
+
|
|
48
|
+
if not converted:
|
|
49
|
+
raise ValueError("created_at is required")
|
|
50
|
+
|
|
51
|
+
return converted
|
|
52
|
+
|
|
53
|
+
@pydantic.validator("updated_at", pre=True)
|
|
54
|
+
@classmethod
|
|
55
|
+
def validate_updated_at(cls, v: str) -> datetime:
|
|
56
|
+
converted = iso_to_date_time(v)
|
|
57
|
+
|
|
58
|
+
if not converted:
|
|
59
|
+
raise ValueError("updated_at is required")
|
|
60
|
+
|
|
61
|
+
return converted
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class IndexStats(CamelBase):
|
|
65
|
+
number_of_documents: int
|
|
66
|
+
is_indexing: bool
|
|
67
|
+
field_distribution: Dict[str, int]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional, Union
|
|
2
|
+
|
|
3
|
+
from camel_converter.pydantic_base import CamelBase
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class FacetHits(CamelBase):
|
|
8
|
+
value: str
|
|
9
|
+
count: int
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class FacetSearchResults(CamelBase):
|
|
13
|
+
facet_hits: List[FacetHits]
|
|
14
|
+
facet_query: str
|
|
15
|
+
processing_time_ms: int
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SearchParams(CamelBase):
|
|
19
|
+
index_uid: str
|
|
20
|
+
query: Optional[str] = Field(None, alias="q")
|
|
21
|
+
offset: int = 0
|
|
22
|
+
limit: int = 20
|
|
23
|
+
filter: Optional[Union[str, List[Union[str, List[str]]]]] = None
|
|
24
|
+
facets: Optional[List[str]] = None
|
|
25
|
+
attributes_to_retrieve: List[str] = ["*"]
|
|
26
|
+
attributes_to_crop: Optional[List[str]] = None
|
|
27
|
+
crop_length: int = 200
|
|
28
|
+
attributes_to_highlight: Optional[List[str]] = None
|
|
29
|
+
sort: Optional[List[str]] = None
|
|
30
|
+
show_matches_position: bool = False
|
|
31
|
+
highlight_pre_tag: str = "<em>"
|
|
32
|
+
highlight_post_tag: str = "</em>"
|
|
33
|
+
crop_marker: str = "..."
|
|
34
|
+
matching_strategy: str = "all"
|
|
35
|
+
hits_per_page: Optional[int] = None
|
|
36
|
+
page: Optional[int] = None
|
|
37
|
+
attributes_to_search_on: Optional[List[str]] = None
|
|
38
|
+
show_ranking_score: bool = False
|
|
39
|
+
show_ranking_score_details: bool = False
|
|
40
|
+
vector: Optional[List[float]] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SearchResults(CamelBase):
|
|
44
|
+
hits: List[Dict[str, Any]]
|
|
45
|
+
offset: Optional[int] = None
|
|
46
|
+
limit: Optional[int] = None
|
|
47
|
+
estimated_total_hits: Optional[int] = None
|
|
48
|
+
processing_time_ms: int
|
|
49
|
+
query: str
|
|
50
|
+
facet_distribution: Optional[Dict[str, Any]] = None
|
|
51
|
+
total_pages: Optional[int] = None
|
|
52
|
+
total_hits: Optional[int] = None
|
|
53
|
+
page: Optional[int] = None
|
|
54
|
+
hits_per_page: Optional[int] = None
|
|
55
|
+
vector: Optional[List[float]] = None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SearchResultsWithUID(SearchResults):
|
|
59
|
+
index_uid: str
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Optional
|
|
2
|
+
|
|
3
|
+
import pydantic
|
|
4
|
+
from camel_converter.pydantic_base import CamelBase
|
|
5
|
+
|
|
6
|
+
from meilisearch_python_sdk._utils import is_pydantic_2
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MinWordSizeForTypos(CamelBase):
|
|
10
|
+
one_typo: Optional[int] = None
|
|
11
|
+
two_typos: Optional[int] = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TypoTolerance(CamelBase):
|
|
15
|
+
enabled: bool = True
|
|
16
|
+
disable_on_attributes: Optional[List[str]] = None
|
|
17
|
+
disable_on_words: Optional[List[str]] = None
|
|
18
|
+
min_word_size_for_typos: Optional[MinWordSizeForTypos] = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Faceting(CamelBase):
|
|
22
|
+
max_values_per_facet: int
|
|
23
|
+
sort_facet_values_by: Optional[Dict[str, str]] = None
|
|
24
|
+
|
|
25
|
+
if is_pydantic_2():
|
|
26
|
+
|
|
27
|
+
@pydantic.field_validator("sort_facet_values_by") # type: ignore[attr-defined]
|
|
28
|
+
@classmethod
|
|
29
|
+
def validate_facet_order(cls, v: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]:
|
|
30
|
+
if not v: # pragma: no cover
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
for _, value in v.items():
|
|
34
|
+
if value not in ("alpha", "count"):
|
|
35
|
+
raise ValueError('facet_order must be either "alpha" or "count"')
|
|
36
|
+
|
|
37
|
+
return v
|
|
38
|
+
|
|
39
|
+
else: # pragma: no cover
|
|
40
|
+
|
|
41
|
+
@pydantic.validator("sort_facet_values_by") # type: ignore[attr-defined]
|
|
42
|
+
@classmethod
|
|
43
|
+
def validate_facet_order(cls, v: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]:
|
|
44
|
+
if not v:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
for _, value in v.items():
|
|
48
|
+
if value not in ("alpha", "count"):
|
|
49
|
+
raise ValueError('facet_order must be either "alpha" or "count"')
|
|
50
|
+
|
|
51
|
+
return v
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Pagination(CamelBase):
|
|
55
|
+
max_total_hits: int
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class MeilisearchSettings(CamelBase):
|
|
59
|
+
synonyms: Optional[Dict[str, Any]] = None
|
|
60
|
+
stop_words: Optional[List[str]] = None
|
|
61
|
+
ranking_rules: Optional[List[str]] = None
|
|
62
|
+
filterable_attributes: Optional[List[str]] = None
|
|
63
|
+
distinct_attribute: Optional[str] = None
|
|
64
|
+
searchable_attributes: Optional[List[str]] = None
|
|
65
|
+
displayed_attributes: Optional[List[str]] = None
|
|
66
|
+
sortable_attributes: Optional[List[str]] = None
|
|
67
|
+
typo_tolerance: Optional[TypoTolerance] = None
|
|
68
|
+
faceting: Optional[Faceting] = None
|
|
69
|
+
pagination: Optional[Pagination] = None
|
|
70
|
+
separator_tokens: Optional[List[str]] = None
|
|
71
|
+
non_separator_tokens: Optional[List[str]] = None
|
|
72
|
+
dictionary: Optional[List[str]] = None
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
|
3
|
+
|
|
4
|
+
import pydantic
|
|
5
|
+
from camel_converter.pydantic_base import CamelBase
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
from meilisearch_python_sdk._utils import is_pydantic_2, iso_to_date_time
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TaskId(CamelBase):
|
|
12
|
+
uid: int
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TaskResult(TaskId):
|
|
16
|
+
index_uid: Optional[str] = None
|
|
17
|
+
status: str
|
|
18
|
+
task_type: Union[str, Dict[str, Any]] = Field(..., alias="type")
|
|
19
|
+
details: Optional[Dict[str, Any]] = None
|
|
20
|
+
error: Optional[Dict[str, Any]] = None
|
|
21
|
+
canceled_by: Optional[int] = None
|
|
22
|
+
duration: Optional[str] = None
|
|
23
|
+
enqueued_at: datetime
|
|
24
|
+
started_at: Optional[datetime] = None
|
|
25
|
+
finished_at: Optional[datetime] = None
|
|
26
|
+
|
|
27
|
+
if is_pydantic_2():
|
|
28
|
+
|
|
29
|
+
@pydantic.field_validator("enqueued_at", mode="before") # type: ignore[attr-defined]
|
|
30
|
+
@classmethod
|
|
31
|
+
def validate_enqueued_at(cls, v: str) -> datetime:
|
|
32
|
+
converted = iso_to_date_time(v)
|
|
33
|
+
|
|
34
|
+
if not converted: # pragma: no cover
|
|
35
|
+
raise ValueError("enqueued_at is required")
|
|
36
|
+
|
|
37
|
+
return converted
|
|
38
|
+
|
|
39
|
+
@pydantic.field_validator("started_at", mode="before") # type: ignore[attr-defined]
|
|
40
|
+
@classmethod
|
|
41
|
+
def validate_started_at(cls, v: str) -> Union[datetime, None]:
|
|
42
|
+
return iso_to_date_time(v)
|
|
43
|
+
|
|
44
|
+
@pydantic.field_validator("finished_at", mode="before") # type: ignore[attr-defined]
|
|
45
|
+
@classmethod
|
|
46
|
+
def validate_finished_at(cls, v: str) -> Union[datetime, None]:
|
|
47
|
+
return iso_to_date_time(v)
|
|
48
|
+
|
|
49
|
+
else: # pragma: no cover
|
|
50
|
+
|
|
51
|
+
@pydantic.validator("enqueued_at", pre=True)
|
|
52
|
+
@classmethod
|
|
53
|
+
def validate_enqueued_at(cls, v: str) -> datetime:
|
|
54
|
+
converted = iso_to_date_time(v)
|
|
55
|
+
|
|
56
|
+
if not converted:
|
|
57
|
+
raise ValueError("enqueued_at is required")
|
|
58
|
+
|
|
59
|
+
return converted
|
|
60
|
+
|
|
61
|
+
@pydantic.validator("started_at", pre=True)
|
|
62
|
+
@classmethod
|
|
63
|
+
def validate_started_at(cls, v: str) -> Union[datetime, None]:
|
|
64
|
+
return iso_to_date_time(v)
|
|
65
|
+
|
|
66
|
+
@pydantic.validator("finished_at", pre=True)
|
|
67
|
+
@classmethod
|
|
68
|
+
def validate_finished_at(cls, v: str) -> Union[datetime, None]:
|
|
69
|
+
return iso_to_date_time(v)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class TaskStatus(CamelBase):
|
|
73
|
+
results: List[TaskResult]
|
|
74
|
+
total: int
|
|
75
|
+
limit: int
|
|
76
|
+
from_: int = Field(..., alias="from")
|
|
77
|
+
next: Optional[int] = None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class TaskInfo(CamelBase):
|
|
81
|
+
task_uid: int
|
|
82
|
+
index_uid: Optional[str] = None
|
|
83
|
+
status: str
|
|
84
|
+
task_type: Union[str, Dict[str, Any]] = Field(..., alias="type")
|
|
85
|
+
enqueued_at: datetime
|
|
86
|
+
|
|
87
|
+
if is_pydantic_2():
|
|
88
|
+
|
|
89
|
+
@pydantic.field_validator("enqueued_at", mode="before") # type: ignore[attr-defined]
|
|
90
|
+
@classmethod
|
|
91
|
+
def validate_enqueued_at(cls, v: str) -> datetime:
|
|
92
|
+
converted = iso_to_date_time(v)
|
|
93
|
+
|
|
94
|
+
if not converted: # pragma: no cover
|
|
95
|
+
raise ValueError("enqueued_at is required")
|
|
96
|
+
|
|
97
|
+
return converted
|
|
98
|
+
|
|
99
|
+
else: # pragma: no cover
|
|
100
|
+
|
|
101
|
+
@pydantic.validator("enqueued_at", pre=True)
|
|
102
|
+
@classmethod
|
|
103
|
+
def validate_enqueued_at(cls, v: str) -> datetime:
|
|
104
|
+
converted = iso_to_date_time(v)
|
|
105
|
+
|
|
106
|
+
if not converted:
|
|
107
|
+
raise ValueError("enqueued_at is required")
|
|
108
|
+
|
|
109
|
+
return converted
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Paul Sanders
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: meilisearch-python-sdk
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: A Python async client for the Meilisearch API
|
|
5
|
+
Home-page: https://github.com/sanders41/meilisearch-python-sdk
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: meilisearch,async,python,client,sdk
|
|
8
|
+
Author: Paul Sanders
|
|
9
|
+
Author-email: psanders1@gmail.com
|
|
10
|
+
Requires-Python: >=3.8,<4.0
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Dist: PyJWT (>=2.3.0)
|
|
23
|
+
Requires-Dist: aiofiles (>=0.7)
|
|
24
|
+
Requires-Dist: camel-converter (>=1.0.0)
|
|
25
|
+
Requires-Dist: httpx (>=0.17)
|
|
26
|
+
Requires-Dist: pydantic (>=1.8)
|
|
27
|
+
Project-URL: Documentation, https://meilisearch-python-sdk.paulsanders.dev
|
|
28
|
+
Project-URL: Repository, https://github.com/sanders41/meilisearch-python-sdk
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Meilisearch Python SDK
|
|
32
|
+
|
|
33
|
+
[](https://github.com/sanders41/meilisearch-python-sdk/actions?query=workflow%3ATesting+branch%3Amain+event%3Apush)
|
|
34
|
+
[](https://results.pre-commit.ci/latest/github/sanders41/meilisearch-python-sdk/main)
|
|
35
|
+
[](https://codecov.io/gh/sanders41/meilisearch-python-sdk)
|
|
36
|
+
[](https://badge.fury.io/py/meilisearch-python-sdk)
|
|
37
|
+
[](https://github.com/sanders41/meilisearch-python-sdk)
|
|
38
|
+
|
|
39
|
+
:warning: This project was previously named `meilisearch-python-async`. Development on that project
|
|
40
|
+
continues here under the new name.
|
|
41
|
+
|
|
42
|
+
Meilisearch Python SDK provides both an async and sync client for the
|
|
43
|
+
[Meilisearch](https://github.com/meilisearch/meilisearch) API.
|
|
44
|
+
|
|
45
|
+
Which client to use depends on your use case. If the code base you are working with uses asyncio,
|
|
46
|
+
for example if you are using [FastAPI](https://fastapi.tiangolo.com/), chose the `AsyncClint`
|
|
47
|
+
otherwise chose the `Client`. The functionality of the two clients is the same, the difference
|
|
48
|
+
being the `AsyncClient` provides async methods and uses the `AsyncIndex`, which also provides async
|
|
49
|
+
methods, while the `Client` provides blocking methods and uses the `Index`, which also provides
|
|
50
|
+
blocking methods.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
Using a virtual environmnet is recommended for installing this package. Once the virtual
|
|
55
|
+
environment is created and activated install the package with:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
pip install meilisearch-python-sdk
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Run Meilisearch
|
|
62
|
+
|
|
63
|
+
There are several ways to
|
|
64
|
+
[run Meilisearch](https://docs.meilisearch.com/reference/features/installation.html#download-and-launch).
|
|
65
|
+
Pick the one that works best for your use case and then start the server.
|
|
66
|
+
|
|
67
|
+
As as example to use Docker:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
docker pull getmeili/meilisearch:latest
|
|
71
|
+
docker run -it --rm -p 7700:7700 getmeili/meilisearch:latest ./meilisearch --master-key=masterKey
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Useage
|
|
75
|
+
|
|
76
|
+
### Add Documents
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
#### AsyncClient
|
|
80
|
+
|
|
81
|
+
- Note: `client.index("books") creates an instance of an AsyncIndex object but does not make a
|
|
82
|
+
network call to send the data yet so it does not need to be awaited.
|
|
83
|
+
|
|
84
|
+
```py
|
|
85
|
+
from meilisearch_python_sdk import AsyncClient
|
|
86
|
+
|
|
87
|
+
async with AsyncClient('http://127.0.0.1:7700', 'masterKey') as client:
|
|
88
|
+
index = client.index("books")
|
|
89
|
+
|
|
90
|
+
documents = [
|
|
91
|
+
{"id": 1, "title": "Ready Player One"},
|
|
92
|
+
{"id": 42, "title": "The Hitchhiker's Guide to the Galaxy"},
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
await index.add_documents(documents)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Client
|
|
99
|
+
|
|
100
|
+
```py
|
|
101
|
+
from meilisearch_python_sdk import Client
|
|
102
|
+
|
|
103
|
+
client = Client('http://127.0.0.1:7700', 'masterKey')
|
|
104
|
+
index = client.index("books")
|
|
105
|
+
|
|
106
|
+
documents = [
|
|
107
|
+
{"id": 1, "title": "Ready Player One"},
|
|
108
|
+
{"id": 42, "title": "The Hitchhiker's Guide to the Galaxy"},
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
index.add_documents(documents)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The server will return an update id that can be used to
|
|
115
|
+
[get the status](https://docs.meilisearch.com/reference/api/updates.html#get-an-update-status)
|
|
116
|
+
of the updates. To do this you would save the result response from adding the documets to a
|
|
117
|
+
variable, this will be a UpdateId object, and use it to check the status of the updates.
|
|
118
|
+
|
|
119
|
+
#### AsyncClient
|
|
120
|
+
|
|
121
|
+
```py
|
|
122
|
+
update = await index.add_documents(documents)
|
|
123
|
+
status = await client.index('books').get_update_status(update.update_id)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Client
|
|
127
|
+
|
|
128
|
+
```py
|
|
129
|
+
update = index.add_documents(documents)
|
|
130
|
+
status = client.index('books').get_update_status(update.update_id)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Basic Searching
|
|
134
|
+
|
|
135
|
+
#### AsyncClient
|
|
136
|
+
|
|
137
|
+
```py
|
|
138
|
+
search_result = await index.search("ready player")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Client
|
|
142
|
+
|
|
143
|
+
```py
|
|
144
|
+
search_result = index.search("ready player")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Base Search Results: SearchResults object with values
|
|
148
|
+
|
|
149
|
+
```py
|
|
150
|
+
SearchResults(
|
|
151
|
+
hits = [
|
|
152
|
+
{
|
|
153
|
+
"id": 1,
|
|
154
|
+
"title": "Ready Player One",
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
offset = 0,
|
|
158
|
+
limit = 20,
|
|
159
|
+
nb_hits = 1,
|
|
160
|
+
exhaustive_nb_hits = bool,
|
|
161
|
+
facets_distributionn = None,
|
|
162
|
+
processing_time_ms = 1,
|
|
163
|
+
query = "ready player",
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Custom Search
|
|
168
|
+
|
|
169
|
+
Information about the parameters can be found in the
|
|
170
|
+
[search parameters](https://docs.meilisearch.com/reference/features/search_parameters.html) section
|
|
171
|
+
of the documentation.
|
|
172
|
+
|
|
173
|
+
#### AsyncClient
|
|
174
|
+
|
|
175
|
+
```py
|
|
176
|
+
await index.search(
|
|
177
|
+
"guide",
|
|
178
|
+
attributes_to_highlight=["title"],
|
|
179
|
+
filters="book_id > 10"
|
|
180
|
+
)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Client
|
|
184
|
+
|
|
185
|
+
```py
|
|
186
|
+
index.search(
|
|
187
|
+
"guide",
|
|
188
|
+
attributes_to_highlight=["title"],
|
|
189
|
+
filters="book_id > 10"
|
|
190
|
+
)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Custom Search Results: SearchResults object with values
|
|
194
|
+
|
|
195
|
+
```py
|
|
196
|
+
SearchResults(
|
|
197
|
+
hits = [
|
|
198
|
+
{
|
|
199
|
+
"id": 42,
|
|
200
|
+
"title": "The Hitchhiker's Guide to the Galaxy",
|
|
201
|
+
"_formatted": {
|
|
202
|
+
"id": 42,
|
|
203
|
+
"title": "The Hitchhiker's Guide to the <em>Galaxy</em>"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
offset = 0,
|
|
208
|
+
limit = 20,
|
|
209
|
+
nb_hits = 1,
|
|
210
|
+
exhaustive_nb_hits = bool,
|
|
211
|
+
facets_distributionn = None,
|
|
212
|
+
processing_time_ms = 5,
|
|
213
|
+
query = "galaxy",
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Benchmark
|
|
218
|
+
|
|
219
|
+
The following benchmarks compare this library to the official
|
|
220
|
+
[Meilisearch Python](https://github.com/meilisearch/meilisearch-python) library. Note that all
|
|
221
|
+
of the performance gains seen with the `AsyncClient` are achieved by taking advantage of asyncio.
|
|
222
|
+
This means that if your code is not taking advantage of asyncio or blocking the event loop the
|
|
223
|
+
gains here will not be seen and the performance between the clients will be very close to the same.
|
|
224
|
+
|
|
225
|
+
### Add Documents in Batches
|
|
226
|
+
|
|
227
|
+
This test compares how long it takes to send 1 million documents in batches of 1 thousand to the
|
|
228
|
+
Meilisearch server for indexing (lower is better). The time does not take into account how long
|
|
229
|
+
Meilisearch takes to index the documents since that is outside of the library functionality.
|
|
230
|
+
|
|
231
|
+

|
|
232
|
+
|
|
233
|
+
### Muiltiple Searches
|
|
234
|
+
|
|
235
|
+
This test compares how long it takes to complete 1000 searches (lower is better)
|
|
236
|
+
|
|
237
|
+

|
|
238
|
+
|
|
239
|
+
### Independent testing
|
|
240
|
+
|
|
241
|
+
[Prashanth Rao](https://github.com/prrao87) did some independent testing and found this async client
|
|
242
|
+
to be ~30% faster than the sync client for data ingestion. You can find a good write-up of the
|
|
243
|
+
results how he tested them in his [blog post](https://thedataquarry.com/posts/meilisearch-async/).
|
|
244
|
+
|
|
245
|
+
## Documentation
|
|
246
|
+
|
|
247
|
+
See our [docs](https://meilisearch-python-sdk.paulsanders.dev) for the full documentation.
|
|
248
|
+
|
|
249
|
+
## Contributing
|
|
250
|
+
|
|
251
|
+
Contributions to this project are welcome. If you are interested in contributing please see our
|
|
252
|
+
[contributing guide](CONTRIBUTING.md)
|
|
253
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
meilisearch_python_sdk/__init__.py,sha256=2MyxnAmiZgA3M_pP_WW7p__dasT6xhyrO2--STSrXQk,259
|
|
2
|
+
meilisearch_python_sdk/_client.py,sha256=3piM_YUdrbBgphDmPNlhlxHC0MhTdaT7UL2M__Gbjpk,60671
|
|
3
|
+
meilisearch_python_sdk/_http_requests.py,sha256=eRYosZQI3rfA8iTqMiBopnzWo3TlWEGQd659S-jsZ_U,4829
|
|
4
|
+
meilisearch_python_sdk/_index.py,sha256=r9L7-z-WoepocDD3Yz860zV8G-Em8q9TxU2GnTwNQE4,207964
|
|
5
|
+
meilisearch_python_sdk/_task.py,sha256=HiyrLsQn5O2PlnUsKPc0RLSPZnJMIsiwA3WSmFsU2Qk,11874
|
|
6
|
+
meilisearch_python_sdk/_utils.py,sha256=SMoBWDlLtAEtpD8n94CCcHvtBA-HLWyolxPY-n4K_UE,1610
|
|
7
|
+
meilisearch_python_sdk/_version.py,sha256=hyBh0bE6J-qEFrdhg0HzT5ZFxu3-X1LLCrhPVnUnu0w,18
|
|
8
|
+
meilisearch_python_sdk/errors.py,sha256=0sAKYt47-zFpKsEU6W8Qnvf4uHBynKtlGPpPl-5laSA,2085
|
|
9
|
+
meilisearch_python_sdk/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
meilisearch_python_sdk/models/client.py,sha256=tT97Y-HWrBNiCgj4w7aC_YXtdLpJr0nUE2P-URVZ9Dg,4714
|
|
11
|
+
meilisearch_python_sdk/models/documents.py,sha256=NpAJwsFIUED0wtAsyQ8e_1b43clBdcYpr-TczHVEdnc,202
|
|
12
|
+
meilisearch_python_sdk/models/health.py,sha256=hvruti7ylsk7bAh8RPOhTPcRrjx6MPgdkDFX9vZ5Qks,95
|
|
13
|
+
meilisearch_python_sdk/models/index.py,sha256=gIb7GYlvkLqv4kyI4Xec2IkLFgvZx0w2kz7iEOCNXNU,1845
|
|
14
|
+
meilisearch_python_sdk/models/search.py,sha256=E5jLxyDJXv16dQopA6_pIj0gRQxNkT3i_8RVyfP0lH4,1734
|
|
15
|
+
meilisearch_python_sdk/models/settings.py,sha256=s2TfT3ZnoAc2vyaWbiJheXHMgvD_8AcuKRFkJ7iGzYA,2377
|
|
16
|
+
meilisearch_python_sdk/models/task.py,sha256=fX8AnYEMzF4ZJsO3LQlaEpNJHL-iSCBqFV0y7M1Adew,3324
|
|
17
|
+
meilisearch_python_sdk/models/version.py,sha256=YDu-aj5H-d6nSaWRTXzlwWghmZAoiknaw250UyEd48I,215
|
|
18
|
+
meilisearch_python_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
meilisearch_python_sdk-2.0.0.dist-info/LICENSE,sha256=xVzevI1TrlKfM0plmJ7vfK1Muu0V9n-dGE8RnDrOFlM,1069
|
|
20
|
+
meilisearch_python_sdk-2.0.0.dist-info/METADATA,sha256=xS4ljtwElNZOcQLZ6J7oe-8QK1D0x7xNzYAHxn2U-zc,8182
|
|
21
|
+
meilisearch_python_sdk-2.0.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
|
22
|
+
meilisearch_python_sdk-2.0.0.dist-info/RECORD,,
|