Skip to content

Commit 69f6be1

Browse files
committed
Add sort_facet_values_by to Faceting model
1 parent a4b6513 commit 69f6be1

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

meilisearch/models/index.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
from typing import Any, Dict, Iterator, List, Optional
44

5+
import pydantic
56
from camel_converter import to_snake
67
from camel_converter.pydantic_base import CamelBase
78

9+
from meilisearch._utils import is_pydantic_2
10+
811

912
class IndexStats:
1013
__dict: Dict
@@ -29,6 +32,35 @@ def __iter__(self) -> Iterator:
2932

3033
class Faceting(CamelBase):
3134
max_values_per_facet: int
35+
sort_facet_values_by: Optional[Dict[str, str]] = None
36+
37+
if is_pydantic_2():
38+
39+
@pydantic.field_validator("sort_facet_values_by") # type: ignore[attr-defined]
40+
@classmethod
41+
def validate_facet_order(cls, v: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]:
42+
if not v: # pragma: no cover
43+
return None
44+
45+
for _, value in v.items():
46+
if value not in ("alpha", "count"):
47+
raise ValueError('facet_order must be either "alpha" or "count"')
48+
49+
return v
50+
51+
else: # pragma: no cover
52+
53+
@pydantic.validator("sort_facet_values_by") # type: ignore[attr-defined]
54+
@classmethod
55+
def validate_facet_order(cls, v: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]:
56+
if not v:
57+
return None
58+
59+
for _, value in v.items():
60+
if value not in ("alpha", "count"):
61+
raise ValueError('facet_order must be either "alpha" or "count"')
62+
63+
return v
3264

3365

3466
class Pagination(CamelBase):

tests/settings/test_setting_faceting.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
import pytest
2+
3+
from meilisearch.models.index import Faceting
4+
15
DEFAULT_MAX_VALUE_PER_FACET = 100
6+
DEFAULT_SORT_FACET_VALUES_BY = {"*": "alpha"}
27
NEW_MAX_VALUE_PER_FACET = {"maxValuesPerFacet": 200}
38

49

510
def test_get_faceting_settings(empty_index):
611
response = empty_index().get_faceting_settings()
712

813
assert DEFAULT_MAX_VALUE_PER_FACET == response.max_values_per_facet
14+
assert DEFAULT_SORT_FACET_VALUES_BY == response.sort_facet_values_by
915

1016

1117
def test_update_faceting_settings(empty_index):
@@ -25,3 +31,59 @@ def test_delete_faceting_settings(empty_index):
2531
index.wait_for_task(response.task_uid)
2632
response = index.get_faceting_settings()
2733
assert DEFAULT_MAX_VALUE_PER_FACET == response.max_values_per_facet
34+
35+
36+
@pytest.mark.parametrize(
37+
"index_name, facet_order, max_values_per_facet, expected",
38+
[
39+
("*", "alpha", 17, {"max_values_per_facet": 17, "sort_facet_values_by": {"*": "alpha"}}),
40+
("*", "count", 41, {"max_values_per_facet": 41, "sort_facet_values_by": {"*": "count"}}),
41+
(
42+
"movies",
43+
"alpha",
44+
42,
45+
{"max_values_per_facet": 42, "sort_facet_values_by": {"*": "alpha", "movies": "alpha"}},
46+
),
47+
(
48+
"movies",
49+
"alpha",
50+
73,
51+
{"max_values_per_facet": 73, "sort_facet_values_by": {"*": "alpha", "movies": "alpha"}},
52+
),
53+
],
54+
)
55+
def test_update_faceting_sort_facet_values(
56+
index_name, facet_order, max_values_per_facet, expected, empty_index
57+
):
58+
faceting = Faceting(
59+
max_values_per_facet=max_values_per_facet,
60+
sort_facet_values_by={index_name: facet_order},
61+
)
62+
index = empty_index()
63+
response = index.update_faceting_settings(faceting.model_dump(by_alias=True))
64+
index.wait_for_task(response.task_uid)
65+
response = index.get_faceting_settings()
66+
assert response.model_dump() == expected
67+
68+
69+
def test_update_faceting_sort_facet_values_invalid_sort_type():
70+
with pytest.raises(ValueError):
71+
Faceting(
72+
max_values_per_facet=2,
73+
sort_facet_values_by={"*": "bad"},
74+
)
75+
76+
77+
def test_reset_faceting(empty_index):
78+
index = empty_index()
79+
response = index.update_faceting_settings(
80+
{"maxValuesPerFacet": 17, "sortFacetValuesBy": {"*": "count"}}
81+
)
82+
index.wait_for_task(response.task_uid)
83+
response = index.reset_faceting_settings()
84+
index.wait_for_task(response.task_uid)
85+
response = index.get_faceting_settings()
86+
assert response == Faceting(
87+
max_values_per_facet=DEFAULT_MAX_VALUE_PER_FACET,
88+
sort_facet_values_by=DEFAULT_SORT_FACET_VALUES_BY,
89+
)

0 commit comments

Comments
 (0)