Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods for new index settings: facetSearch and prefixSearch #1068

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,12 @@ update_pagination_settings_1: |-
client.index('books').update_pagination_settings({'maxTotalHits': 100})
reset_pagination_settings_1: |-
client.index('books').reset_pagination_settings()
get_facet_search_settings_1: |-
client.index('books').get_facet_search_settings()
update_facet_search_settings_1: |-
client.index('books').update_facet_search_settings(False)
reset_facet_search_settings_1: |-
client.index('books').reset_facet_search_settings()
get_faceting_settings_1: |-
client.index('books').get_faceting_settings()
update_faceting_settings_1: |-
Expand Down Expand Up @@ -724,6 +730,12 @@ update_search_cutoff_1: |-
client.index('movies').update_search_cutoff_ms(150)
reset_search_cutoff_1: |-
client.index('movies').reset_search_cutoff_ms()
get_prefix_search_settings_1: |-
client.index('books').get_prefix_search()
update_prefix_search_settings_1: |-
client.index('books').update_prefix_search(PrefixSearch.DISABLED)
reset_prefix_search_settings_1: |-
client.index('books').reset_prefix_search()
get_proximity_precision_settings_1: |-
client.index('books').get_proximity_precision()
update_proximity_precision_settings_1: |-
Expand Down
7 changes: 5 additions & 2 deletions meilisearch/_httprequests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
MeilisearchCommunicationError,
MeilisearchTimeoutError,
)
from meilisearch.models.index import ProximityPrecision
from meilisearch.models.index import PrefixSearch, ProximityPrecision
from meilisearch.version import qualified_version


Expand All @@ -33,6 +33,7 @@ def send_request(
Mapping[str, Any],
Sequence[Mapping[str, Any]],
List[str],
bool,
bytes,
str,
int,
Expand Down Expand Up @@ -64,7 +65,7 @@ def send_request(
serialize_body = isinstance(body, dict) or body
data = (
json.dumps(body, cls=serializer)
if serialize_body
if isinstance(body, bool) or serialize_body
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these nested ifs are bit convoluted. But I decided not revamping them now :) Previous PRs suggest it might be for backward compatibility

else "" if body == "" else "null"
)

Expand Down Expand Up @@ -111,9 +112,11 @@ def put(
Mapping[str, Any],
Sequence[Mapping[str, Any]],
List[str],
bool,
bytes,
str,
int,
PrefixSearch,
ProximityPrecision,
]
] = None,
Expand Down
1 change: 1 addition & 0 deletions meilisearch/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Paths:
swap = "swap-indexes"
embedders = "embedders"
search_cutoff_ms = "search-cutoff-ms"
prefix_search = "prefix-search"
proximity_precision = "proximity-precision"
localized_attributes = "localized-attributes"

Expand Down
105 changes: 104 additions & 1 deletion meilisearch/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
LocalizedAttributes,
OpenAiEmbedder,
Pagination,
PrefixSearch,
ProximityPrecision,
TypoTolerance,
UserProvidedEmbedder,
Expand Down Expand Up @@ -1628,6 +1629,57 @@ def reset_pagination_settings(self) -> TaskInfo:

return TaskInfo(**task)

def get_facet_search_settings(self) -> bool:
"""Get the facet search settings of an index.

Returns
-------
bool:
True if facet search is enabled, False if disabled.
Raises
------
MeilisearchApiError
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
"""

return self.http.get(self.__settings_url_for(self.config.paths.facet_search))

def update_facet_search_settings(self, body: Union[bool, None]) -> TaskInfo:
"""Update the facet search settings of the index.

Parameters
----------
body: bool
True to enable facet search, False to disable it.

Returns
-------
task_info:
TaskInfo instance containing information about a task to track the progress of an asynchronous process.
https://www.meilisearch.com/docs/reference/api/tasks#get-one-task

Raises
------
MeilisearchApiError
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
"""
task = self.http.put(self.__settings_url_for(self.config.paths.facet_search), body=body)

return TaskInfo(**task)

def reset_facet_search_settings(self) -> TaskInfo:
"""Reset facet search settings of the index to default values.

Returns
-------
task_info:
TaskInfo instance containing information about a task to track the progress of an asynchronous process.
https://www.meilisearch.com/docs/reference/api/tasks
"""
task = self.http.delete(self.__settings_url_for(self.config.paths.facet_search))

return TaskInfo(**task)

def get_faceting_settings(self) -> Faceting:
"""Get the faceting settings of an index.

Expand All @@ -1641,7 +1693,6 @@ def get_faceting_settings(self) -> Faceting:
MeilisearchApiError
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
"""

faceting = self.http.get(self.__settings_url_for(self.config.paths.faceting))

return Faceting(**faceting)
Expand Down Expand Up @@ -2006,6 +2057,58 @@ def reset_search_cutoff_ms(self) -> TaskInfo:

return TaskInfo(**task)

# PREFIX SEARCH

def get_prefix_search(self) -> PrefixSearch:
"""Get the prefix search settings of an index.

Returns
-------
settings:
The prefix search settings of the index.

Raises
------
MeilisearchApiError
An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors
"""
prefix_search = self.http.get(self.__settings_url_for(self.config.paths.prefix_search))

return PrefixSearch[to_snake(prefix_search).upper()]

def update_prefix_search(self, body: Union[PrefixSearch, None]) -> TaskInfo:
"""Update the prefix search settings of the index.

Parameters
----------
body:
Prefix search settings

Returns
-------
task_info:
TaskInfo instance containing information about a task to track the progress of an asynchronous process.
https://www.meilisearch.com/docs/reference/api/tasks
"""
task = self.http.put(self.__settings_url_for(self.config.paths.prefix_search), body)

return TaskInfo(**task)

def reset_prefix_search(self) -> TaskInfo:
"""Reset the prefix search settings of the index

Returns
-------
task_info:
TaskInfo instance containing information about a task to track the progress of an asynchronous process.
https://www.meilisearch.com/docs/reference/api/tasks
"""
task = self.http.delete(
self.__settings_url_for(self.config.paths.prefix_search),
)

return TaskInfo(**task)

# PROXIMITY PRECISION SETTINGS

def get_proximity_precision(self) -> ProximityPrecision:
Expand Down
12 changes: 12 additions & 0 deletions meilisearch/models/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ class TypoTolerance(CamelBase):
min_word_size_for_typos: Optional[MinWordSizeForTypos] = None


class PrefixSearch(str, Enum):
INDEXING_TIME = "indexingTime"
"""
Calculate prefix search during indexing. This is the default behavior.
"""

DISABLED = "disabled"
"""
Do not calculate prefix search. May speed up indexing, but will severely impact search result relevancy.
"""


class ProximityPrecision(str, Enum):
BY_WORD = "byWord"
BY_ATTRIBUTE = "byAttribute"
Expand Down
38 changes: 38 additions & 0 deletions tests/settings/test_settings_facet_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
DEFAULT_FACET_SEARCH_SETTINGS_STATUS = True
ENABLED_FACET_SEARCH_SETTINGS_STATUS = True
DISABLED_FACET_SEARCH_SETTINGS_STATUS = False


def test_get_facet_search_settings(empty_index):
response = empty_index().get_facet_search_settings()

assert DEFAULT_FACET_SEARCH_SETTINGS_STATUS == response


def test_update_facet_search_settings(empty_index):
index = empty_index()

response = index.update_facet_search_settings(DISABLED_FACET_SEARCH_SETTINGS_STATUS)
index.wait_for_task(response.task_uid)
response = index.get_facet_search_settings()
assert DISABLED_FACET_SEARCH_SETTINGS_STATUS == response

response = index.update_facet_search_settings(ENABLED_FACET_SEARCH_SETTINGS_STATUS)
index.wait_for_task(response.task_uid)
response = index.get_facet_search_settings()
assert ENABLED_FACET_SEARCH_SETTINGS_STATUS == response


def test_reset_facet_search_settings(empty_index):
index = empty_index()

response = index.update_facet_search_settings(DISABLED_FACET_SEARCH_SETTINGS_STATUS)
index.wait_for_task(response.task_uid)
response = index.get_facet_search_settings()
assert DISABLED_FACET_SEARCH_SETTINGS_STATUS == response
assert DEFAULT_FACET_SEARCH_SETTINGS_STATUS != response

response = index.reset_facet_search_settings()
index.wait_for_task(response.task_uid)
response = index.get_facet_search_settings()
assert DEFAULT_FACET_SEARCH_SETTINGS_STATUS == response
38 changes: 38 additions & 0 deletions tests/settings/test_settings_prefix_search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from meilisearch.models.index import PrefixSearch

DEFAULT_PREFIX_SEARCH_SETTINGS = PrefixSearch.INDEXING_TIME


def test_get_prefix_search(empty_index):
response = empty_index().get_prefix_search()

assert DEFAULT_PREFIX_SEARCH_SETTINGS == response


def test_update_prefix_search(empty_index):
index = empty_index()

response = index.update_prefix_search(PrefixSearch.DISABLED)
index.wait_for_task(response.task_uid)
response = index.get_prefix_search()
assert PrefixSearch.DISABLED == response

response = index.update_prefix_search(PrefixSearch.INDEXING_TIME)
index.wait_for_task(response.task_uid)
response = index.get_prefix_search()
assert PrefixSearch.INDEXING_TIME == response


def test_reset_prefix_search(empty_index):
index = empty_index()

response = index.update_prefix_search(PrefixSearch.DISABLED)
index.wait_for_task(response.task_uid)
response = index.get_prefix_search()
assert PrefixSearch.DISABLED == response
assert DEFAULT_PREFIX_SEARCH_SETTINGS != response

response = index.reset_prefix_search()
index.wait_for_task(response.task_uid)
response = index.get_prefix_search()
assert DEFAULT_PREFIX_SEARCH_SETTINGS == response