Skip to content

Commit d1b8fbf

Browse files
committed
feat: add explicit personalize parameter to Index.search
Address review: expose `personalize` as an explicit, typed parameter on `Index.search` and forward it in the request body, instead of only documenting it as an `opt_params` key. Add a test asserting it is serialized correctly.
1 parent ee5952f commit d1b8fbf

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

meilisearch/index.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,12 @@ def get_stats(self) -> IndexStats:
333333
return IndexStats(**stats)
334334

335335
@version_error_hint_message
336-
def search(self, query: str, opt_params: Optional[Mapping[str, Any]] = None) -> Dict[str, Any]:
336+
def search(
337+
self,
338+
query: str,
339+
opt_params: Optional[Mapping[str, Any]] = None,
340+
personalize: Optional[Dict[str, Any]] = None,
341+
) -> Dict[str, Any]:
337342
"""Search in the index.
338343
339344
https://www.meilisearch.com/docs/reference/api/search
@@ -348,13 +353,14 @@ def search(self, query: str, opt_params: Optional[Mapping[str, Any]] = None) ->
348353
- hybrid: Dict with 'semanticRatio' and 'embedder' fields for hybrid search
349354
- vector: Array of numbers for vector search
350355
- retrieveVectors: Boolean to include vector data in search results
351-
- personalize: Dict with a 'userContext' string to personalize the
352-
results (experimental; requires Meilisearch >= v1.47)
353356
- filter: Filter queries by an attribute's value
354357
- limit: Maximum number of documents returned
355358
- offset: Number of documents to skip
356359
- showPerformanceDetails: If true, the response includes a
357360
performanceDetails object (raw data; fields may change in future API versions)
361+
personalize (optional):
362+
Dict with a 'userContext' string to personalize the search results
363+
(experimental; requires Meilisearch >= v1.47).
358364
359365
Returns
360366
-------
@@ -371,6 +377,8 @@ def search(self, query: str, opt_params: Optional[Mapping[str, Any]] = None) ->
371377
opt_params = {}
372378

373379
body = {"q": query, **opt_params}
380+
if personalize is not None:
381+
body["personalize"] = personalize
374382

375383
return self.http.post(
376384
f"{self.config.paths.index}/{self.uid}/{self.config.paths.search}",

tests/index/test_index_search_meilisearch.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pylint: disable=invalid-name
22

33
from collections import Counter
4+
from unittest.mock import patch
45

56
import pytest
67

@@ -14,6 +15,17 @@ def test_basic_search(index_with_documents):
1415
assert "hitsPerPage" is not response
1516

1617

18+
def test_search_serializes_personalize(client):
19+
"""The `personalize` parameter must be forwarded in the search request body."""
20+
index = client.index("books")
21+
with patch.object(index.http, "post", return_value={"hits": []}) as mock_post:
22+
index.search("prince", personalize={"userContext": "user-123"})
23+
24+
_, kwargs = mock_post.call_args
25+
assert kwargs["body"]["q"] == "prince"
26+
assert kwargs["body"]["personalize"] == {"userContext": "user-123"}
27+
28+
1729
def test_basic_search_with_empty_params(index_with_documents):
1830
"""Tests search with a simple query and empty params."""
1931
response = index_with_documents().search("How to Train Your Dragon", {})

0 commit comments

Comments
 (0)