Skip to content

Commit f61935e

Browse files
curquizaeskombrobidoubiwa
authored
Upd package for MeiliSearch v0.11 (#88)
* Upd version * Add method to use faceting sub routes (#90) * Remane apikey into api_key (#93) * Implement faceting in search (#94) * Implement faceting in search * Upd test * Clear all indexes before starting tests in a certain context (#95) * Clear all indexes before starting tests in a certain context * Update meilisearch/tests/__init__.py Co-authored-by: Samuel Jimenez <[email protected]> Co-authored-by: Samuel Jimenez <[email protected]> * Upd version * Add method to use faceting sub routes (#90) * Remane apikey into api_key (#93) * Implement faceting in search (#94) * Implement faceting in search * Upd test * Fix parameter default value (#97) * Add test with multiple facetFilters (#98) * Change create_index prototype (#99) * Change create_index prototype * Update meilisearch/client.py Co-authored-by: cvermand <[email protected]> * Update meilisearch/index.py Co-authored-by: cvermand <[email protected]> Co-authored-by: cvermand <[email protected]> Co-authored-by: Samuel Jimenez <[email protected]> Co-authored-by: cvermand <[email protected]>
1 parent 04bfb17 commit f61935e

19 files changed

+276
-56
lines changed

README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
- [⚙️ Development Workflow](#️-development-workflow)
3838
- [Install dependencies](#install-dependencies)
3939
- [Tests and Linter](#tests-and-linter)
40+
- [Want to debug?](#want-to-debug)
4041
- [Release](#release)
4142

4243
## 🔧 Installation
@@ -66,8 +67,8 @@ NB: you can also download MeiliSearch from **Homebrew** or **APT**.
6667
import meilisearch
6768

6869
client = meilisearch.Client('http://127.0.0.1:7700', 'masterKey')
69-
index = client.create_index(uid='books') # If your index does not exist
70-
index = client.get_index('books') # If you already created your index
70+
index = client.create_index('books') # If your index does not exist
71+
index = client.get_index('books') # If you already created your index
7172

7273
documents = [
7374
{ 'book_id': 123, 'title': 'Pride and Prejudice' },
@@ -106,7 +107,7 @@ Output:
106107
## 🤖 Compatibility with MeiliSearch
107108

108109
This package is compatible with the following MeiliSearch versions:
109-
- `v0.10.X`
110+
- `v0.11.X`
110111

111112
## 🎬 Examples
112113

@@ -117,9 +118,9 @@ You can check out [the API documentation](https://docs.meilisearch.com/reference
117118
#### Create an index <!-- omit in toc -->
118119
```python
119120
# Create an index
120-
client.create_index(uid='books')
121+
client.create_index('books')
121122
# Create an index and give the primary-key
122-
client.create_index(uid='books', primary_key='book_id')
123+
client.create_index('books', {'primaryKey': 'book_id'})
123124
```
124125

125126
#### List all indexes <!-- omit in toc -->
@@ -253,6 +254,20 @@ $ pipenv run pytest meilisearch
253254
$ pipenv run pylint meilisearch
254255
```
255256

257+
### Want to debug?
258+
259+
Import `pdb` in your file and use it:
260+
261+
```python
262+
import pdb
263+
264+
...
265+
pdb.set_trace() # create a break point
266+
...
267+
```
268+
269+
More information [about pdb](https://docs.python.org/3/library/pdb.html).
270+
256271
### Release
257272

258273
MeiliSearch tools follow the [Semantic Versioning Convention](https://semver.org/).

datasets/small_movies.json

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
"title": "Shazam!",
55
"poster": "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
66
"overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
7-
"release_date": 1553299200
7+
"release_date": 1553299200,
8+
"genre": "action"
89
},
910
{
1011
"id": "299537",
1112
"title": "Captain Marvel",
1213
"poster": "https://image.tmdb.org/t/p/w1280/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
1314
"overview": "The story follows Carol Danvers as she becomes one of the universe’s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
14-
"release_date": 1551830400
15+
"release_date": 1551830400,
16+
"genre": "action"
1517
},
1618
{
1719
"id": "522681",
@@ -25,7 +27,8 @@
2527
"title": "How to Train Your Dragon: The Hidden World",
2628
"poster": "https://image.tmdb.org/t/p/w1280/xvx4Yhf0DVH8G4LzNISpMfFBDy2.jpg",
2729
"overview": "As Hiccup fulfills his dream of creating a peaceful dragon utopia, Toothless’ discovery of an untamed, elusive mate draws the Night Fury away. When danger mounts at home and Hiccup’s reign as village chief is tested, both dragon and rider must make impossible decisions to save their kind.",
28-
"release_date": 1546473600
30+
"release_date": 1546473600,
31+
"genre": "cartoon"
2932
},
3033
{
3134
"id": "450465",
@@ -46,14 +49,16 @@
4649
"title": "Dumbo",
4750
"poster": "https://image.tmdb.org/t/p/w1280/279PwJAcelI4VuBtdzrZASqDPQr.jpg",
4851
"overview": "A young elephant, whose oversized ears enable him to fly, helps save a struggling circus, but when the circus plans a new venture, Dumbo and his friends discover dark secrets beneath its shiny veneer.",
49-
"release_date": 1553644800
52+
"release_date": 1553644800,
53+
"genre": "cartoon"
5054
},
5155
{
5256
"id": "299536",
5357
"title": "Avengers: Infinity War",
5458
"poster": "https://image.tmdb.org/t/p/w1280/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
5559
"overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.",
56-
"release_date": 1524618000
60+
"release_date": 1524618000,
61+
"genre": "action"
5762
},
5863
{
5964
"id": "458723",
@@ -74,21 +79,24 @@
7479
"title": "Cars",
7580
"poster": "https://image.tmdb.org/t/p/w1280/5damnMcRFKSjhCirgX3CMa88MBj.jpg",
7681
"overview": "Lightning McQueen, a hotshot rookie race car driven to succeed, discovers that life is about the journey, not the finish line, when he finds himself unexpectedly detoured in the sleepy Route 66 town of Radiator Springs. On route across the country to the big Piston Cup Championship in California to compete against two seasoned pros, McQueen gets to know the town's offbeat characters.",
77-
"release_date": 1149728400
82+
"release_date": 1149728400,
83+
"genre": "cartoon"
7884
},
7985
{
8086
"id": "299534",
8187
"title": "Avengers: Endgame",
8288
"poster": "https://image.tmdb.org/t/p/w1280/dHjLaIUHXcMBt7YxK1TKWK1end9.jpg",
8389
"overview": "After the devastating events of Avengers: Infinity War, the universe is in ruins due to the efforts of the Mad Titan, Thanos. With the help of remaining allies, the Avengers must assemble once more in order to undo Thanos' actions and restore order to the universe once and for all, no matter what consequences may be in store.",
84-
"release_date": 1556067600
90+
"release_date": 1556067600,
91+
"genre": "action"
8592
},
8693
{
8794
"id": "324857",
8895
"title": "Spider-Man: Into the Spider-Verse",
8996
"poster": "https://image.tmdb.org/t/p/w1280/iiZZdoQBEYBv6id8su7ImL0oCbD.jpg",
9097
"overview": "Miles Morales is juggling his life between being a high school student and being a spider-man. When Wilson 'Kingpin' Fisk uses a super collider, others from across the Spider-Verse are transported to this dimension.",
91-
"release_date": 1544140800
98+
"release_date": 1544140800,
99+
"genre": "action"
92100
},
93101
{
94102
"id": "157433",
@@ -137,7 +145,8 @@
137145
"title": "Aquaman",
138146
"poster": "https://image.tmdb.org/t/p/w1280/5Kg76ldv7VxeX9YlcQXiowHgdX6.jpg",
139147
"overview": "Once home to the most advanced civilization on Earth, Atlantis is now an underwater kingdom ruled by the power-hungry King Orm. With a vast army at his disposal, Orm plans to conquer the remaining oceanic people and then the surface world. Standing in his way is Arthur Curry, Orm's half-human, half-Atlantean brother and true heir to the throne.",
140-
"release_date": 1544140800
148+
"release_date": 1544140800,
149+
"genre": "action"
141150
},
142151
{
143152
"id": "512196",
@@ -186,7 +195,8 @@
186195
"title": "Fantastic Beasts: The Crimes of Grindelwald",
187196
"poster": "https://image.tmdb.org/t/p/w1280/fMMrl8fD9gRCFJvsx0SuFwkEOop.jpg",
188197
"overview": "Gellert Grindelwald has escaped imprisonment and has begun gathering followers to his cause—elevating wizards above all non-magical beings. The only one capable of putting a stop to him is the wizard he once called his closest friend, Albus Dumbledore. However, Dumbledore will need to seek help from the wizard who had thwarted Grindelwald once before, his former student Newt Scamander, who agrees to help, unaware of the dangers that lie ahead. Lines are drawn as love and loyalty are tested, even among the truest friends and family, in an increasingly divided wizarding world.",
189-
"release_date": 1542153600
198+
"release_date": 1542153600,
199+
"genre": "fantasy"
190200
},
191201
{
192202
"id": "399579",

meilisearch/_httprequests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class HttpRequests:
99
def __init__(self, config):
1010
self.config = config
1111
self.headers = {
12-
'X-Meili-Api-Key': self.config.apikey,
12+
'X-Meili-Api-Key': self.config.api_key,
1313
'Content-Type': 'application/json'
1414
}
1515

meilisearch/client.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self, url, apiKey=None):
2525
self.config = Config(url, apiKey)
2626
self.http = HttpRequests(self.config)
2727

28-
def create_index(self, uid, primary_key=None, name=None):
28+
def create_index(self, uid, options=None):
2929
"""Create an index.
3030
3131
If the argument `uid` isn't passed in, it will be generated
@@ -35,10 +35,9 @@ def create_index(self, uid, primary_key=None, name=None):
3535
----------
3636
uid: str
3737
UID of the index
38-
primary_key: str, optional
39-
Attribute used as unique document identifier
40-
name: str, optional
41-
Name of the index
38+
options: dict, optional
39+
Options passed during index creation (ex: primaryKey)
40+
4241
Returns
4342
-------
4443
index : Index
@@ -48,8 +47,8 @@ def create_index(self, uid, primary_key=None, name=None):
4847
HTTPError
4948
In case of any other error found here https://docs.meilisearch.com/references/#errors-status-code
5049
"""
51-
index = Index(self.config, uid=uid)
52-
index.create(self.config, uid=uid, primary_key=primary_key, name=name)
50+
index = Index(self.config, uid)
51+
index.create(self.config, uid, options)
5352
return index
5453

5554
def get_indexes(self):

meilisearch/config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@ class Paths():
2121
stop_words = 'stop-words'
2222
synonyms = 'synonyms'
2323
accept_new_fields = 'accept-new-fields'
24+
attributes_for_faceting = 'attributes-for-faceting'
2425

25-
def __init__(self, url, apikey=None):
26+
def __init__(self, url, api_key=None):
2627
"""
2728
Parameters
2829
----------
2930
url : str
3031
The url to the MeiliSearch API (ex: http://localhost:7700)
31-
apikey : str
32+
api_key : str
3233
The optional API key to access MeiliSearch
3334
"""
3435

3536
self.url = url
36-
self.apikey = apikey
37+
self.api_key = api_key
3738
self.paths = self.Paths()

meilisearch/index.py

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import urllib
23
from datetime import datetime
34
from time import sleep
@@ -83,13 +84,15 @@ def get_primary_key(self):
8384
return self.info()['primaryKey']
8485

8586
@staticmethod
86-
def create(config, **body):
87+
def create(config, uid, options=None):
8788
"""Create an index.
8889
8990
Parameters
9091
----------
91-
body: **kwargs
92-
Accepts uid, name and primaryKey as parameter.
92+
uid: str
93+
UID of the index
94+
options: dict, optional
95+
Options passed during index creation (ex: primaryKey)
9396
9497
Returns
9598
-------
@@ -100,16 +103,9 @@ def create(config, **body):
100103
HTTPError
101104
In case of any error found here https://docs.meilisearch.com/references/#errors-status-code
102105
"""
103-
payload = {}
104-
uid = body.get('uid', None)
105-
if uid is not None:
106-
payload['uid'] = uid
107-
name = body.get('name', None)
108-
if name is not None:
109-
payload['name'] = name
110-
primary_key = body.get('primary_key', None)
111-
if primary_key is not None:
112-
payload['primaryKey'] = primary_key
106+
if options is None:
107+
options = {}
108+
payload = {'uid': uid, **options}
113109
return HttpRequests(config).post(config.paths.index, payload)
114110

115111
@staticmethod
@@ -243,13 +239,18 @@ def search(self, query, opt_params=None):
243239
results: `dict`
244240
Dictionnary with hits, offset, limit, processingTime and initial query
245241
"""
242+
# Query parameters parsing
246243
if opt_params is None:
247244
opt_params = {}
248-
search_param = {'q': query}
249245
for key in opt_params:
250-
if isinstance(opt_params[key], list):
246+
if key in ('facetsDistribution', 'facetFilters'):
247+
opt_params[key] = json.dumps(opt_params[key])
248+
elif isinstance(opt_params[key], list):
251249
opt_params[key] = ','.join(opt_params[key])
252-
params = {**search_param, **opt_params}
250+
params = {
251+
'q': query,
252+
**opt_params
253+
}
253254
return self.http.get(
254255
'{}/{}/{}?{}'.format(
255256
self.config.paths.index,
@@ -814,6 +815,54 @@ def update_accept_new_fields(self, body):
814815
body
815816
)
816817

818+
# ATTRIBUTES FOR FACETING SUB-ROUTES
819+
820+
def get_attributes_for_faceting(self):
821+
"""
822+
Get attributes for faceting of an index
823+
824+
Returns
825+
----------
826+
settings: `list`
827+
List containing the attributes for faceting of the index
828+
"""
829+
return self.http.get(
830+
self.__settings_url_for(self.config.paths.attributes_for_faceting)
831+
)
832+
833+
def update_attributes_for_faceting(self, body):
834+
"""
835+
Update attributes for faceting of an index
836+
837+
Parameters
838+
----------
839+
body: `list`
840+
List containing the attributes for faceting
841+
842+
Returns
843+
----------
844+
update: `dict`
845+
Dictionnary containing an update id to track the action:
846+
https://docs.meilisearch.com/references/updates.html#get-an-update-status
847+
"""
848+
return self.http.post(
849+
self.__settings_url_for(self.config.paths.attributes_for_faceting),
850+
body
851+
)
852+
853+
def reset_attributes_for_faceting(self):
854+
"""Reset attributes for faceting of an index to default values
855+
856+
Returns
857+
----------
858+
update: `dict`
859+
Dictionnary containing an update id to track the action:
860+
https://docs.meilisearch.com/references/updates.html#get-an-update-status
861+
"""
862+
return self.http.delete(
863+
self.__settings_url_for(self.config.paths.attributes_for_faceting),
864+
)
865+
817866
def __settings_url_for(self, sub_route):
818867
return '{}/{}/{}/{}'.format(
819868
self.config.paths.index,

meilisearch/tests/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
MASTER_KEY = 'masterKey'
22
BASE_URL = 'http://127.0.0.1:7700'
3+
4+
def clear_all_indexes(client):
5+
indexes = client.get_indexes()
6+
for index in indexes:
7+
client.get_index(index['uid']).delete()

meilisearch/tests/client/test_client_stats_meilisearch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import meilisearch
2-
from meilisearch.tests import BASE_URL, MASTER_KEY
2+
from meilisearch.tests import BASE_URL, MASTER_KEY, clear_all_indexes
33

44
class TestStats:
55

@@ -10,6 +10,7 @@ class TestStats:
1010
index2 = None
1111

1212
def setup_class(self):
13+
clear_all_indexes(self.client)
1314
self.index = self.client.create_index(uid='indexUID')
1415
self.index_2 = self.client.create_index(uid='indexUID2')
1516

meilisearch/tests/client/test_client_sysinfo_meilisearch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import meilisearch
2-
from meilisearch.tests import BASE_URL, MASTER_KEY
2+
from meilisearch.tests import BASE_URL, MASTER_KEY, clear_all_indexes
33

44
class TestSysInfo:
55

@@ -9,6 +9,7 @@ class TestSysInfo:
99
index = None
1010

1111
def setup_class(self):
12+
clear_all_indexes(self.client)
1213
self.index = self.client.create_index(uid='indexUID')
1314

1415
def teardown_class(self):

meilisearch/tests/client/test_client_version_meilisearch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import meilisearch
2-
from meilisearch.tests import BASE_URL, MASTER_KEY
2+
from meilisearch.tests import BASE_URL, MASTER_KEY, clear_all_indexes
33

44
class TestVersion:
55
""" TESTS: version route """
@@ -8,6 +8,7 @@ class TestVersion:
88
index = None
99

1010
def setup_class(self):
11+
clear_all_indexes(self.client)
1112
self.index = self.client.create_index(uid='indexUID')
1213

1314
def teardown_class(self):

0 commit comments

Comments
 (0)