Skip to content
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
# This value contains a list of modules to be mocked up.
autodoc_mock_imports = ["camel_converter"]

html_title = 'Meilisearch Python | Documentation'
html_title = "Meilisearch Python | Documentation"

# Add Fathom analytics script
html_js_files = [
("https://cdn.usefathom.com/script.js", { "data-site": "QNBPJXIV", "defer": "defer" })
("https://cdn.usefathom.com/script.js", {"data-site": "QNBPJXIV", "defer": "defer"})
]
5 changes: 4 additions & 1 deletion meilisearch/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,10 @@ def swap_indexes(self, parameters: List[Mapping[str, List[str]]]) -> TaskInfo:
Parameters
----------
indexes:
List of indexes to swap (ex: [{"indexes": ["indexA", "indexB"]}).
List of indexes to swap ex:
1: {"indexes": ["indexA", "indexB"]} # default rename to false
2: {"indexes": ["indexA", "indexB"], "rename": false}
3: {"indexes": ["indexA", "indexB"], "rename": true}

Returns
-------
Expand Down
26 changes: 24 additions & 2 deletions meilisearch/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,24 @@ def delete(self) -> TaskInfo:

return TaskInfo(**task)

def update(self, primary_key: str) -> TaskInfo:
def update(self, primary_key: Optional[str] = None, new_uid: Optional[str] = None) -> TaskInfo:
"""Update the index primary-key.

Parameters
----------
primary_key:
The primary key to use for the index.
new_uid : str, optional
The new UID to rename the index.

Renaming behavior
-----------------
When ``new_uid`` is provided, this method sends a PATCH request to rename
the index. After the task completes, the index exists under the new UID,
but this ``Index`` instance still contains the old ``self.uid``, making it
**stale**. Further operations with this instance will fail until a fresh
instance is obtained. After the rename task completes, obtain a new ``Index``
instance via ``client.index(new_uid)`` before making further requests.

Returns
-------
Expand All @@ -123,7 +134,18 @@ def update(self, primary_key: str) -> TaskInfo:
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
"""
payload = {"primaryKey": primary_key}
if primary_key is None and new_uid is None:
raise ValueError(
"You must provide either 'primary_key' or 'new_uid' to update the index."
)

payload = {}
if primary_key is not None:
payload["primaryKey"] = primary_key

if new_uid is not None:
payload["uid"] = new_uid # This enables renaming

task = self.http.patch(f"{self.config.paths.index}/{self.uid}", payload)

return TaskInfo(**task)
Expand Down
32 changes: 32 additions & 0 deletions tests/client/test_client_swap_meilisearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ def test_swap_indexes_with_one_that_does_not_exist(client, empty_index):
assert task.error["code"] == "index_not_found"


def test_swap_indexes_with_one_that_does_not_exist_with_rename_as_false(client, empty_index):
"""Tests swap indexes with one that does not exist."""
index = empty_index("index_A")
swapTask = client.swap_indexes(
[
{"indexes": [index.uid, "does_not_exist"], "rename": False},
]
)
task = client.wait_for_task(swapTask.task_uid)

assert swapTask.type == "indexSwap"
assert task.error["code"] == "index_not_found"


def test_swap_indexes_with_itself(client, empty_index):
"""Tests swap indexes with itself."""
index = empty_index()
Expand All @@ -57,3 +71,21 @@ def test_swap_indexes_with_itself(client, empty_index):
},
]
)


def test_swap_indexes_with_one_that_does_not_exist_with_rename_as_true(client, empty_index):
"""Tests swap indexes with one that does not exist."""
index = empty_index("index_B")
renamed_index_name = "new_index_name"
swapTask = client.swap_indexes(
[
{"indexes": [index.uid, renamed_index_name], "rename": True},
]
)
client.wait_for_task(swapTask.task_uid)
assert swapTask.type == "indexSwap"

# Verify the new index UID exists
renamed_index = client.index(renamed_index_name)
info = renamed_index.fetch_info()
assert info.uid == renamed_index_name
49 changes: 49 additions & 0 deletions tests/index/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,52 @@ def test_index_compact(client):

assert stats_before.number_of_documents == stats_after.number_of_documents
assert stats_after.is_indexing is False


@pytest.mark.usefixtures("indexes_sample")
def test_rename_index(client):
"""Test renaming an existing index."""
original_uid = common.INDEX_UID
new_uid = f"{original_uid}_renamed"
index = client.index(original_uid)

# Perform the rename
task_info = index.update(new_uid=new_uid)
client.wait_for_task(task_info.task_uid)

# Verify the index now exists with the new UID
renamed_index = client.index(new_uid)
info = renamed_index.fetch_info()
assert info.uid == new_uid

# # Verify the old UID no longer exists
with pytest.raises(MeilisearchApiError):
client.index(original_uid).fetch_info() # Assert old UID is gone


@pytest.mark.usefixtures("indexes_sample")
def test_index_update_and_rename(client):
"""Test updating primary key and renaming an index together."""
original_uid = common.INDEX_UID
new_uid = f"{original_uid}_renamed"
index = client.index(original_uid)

# 1. Update the primary key
task_info = index.update(primary_key="objectID", new_uid=new_uid)
client.wait_for_task(task_info.task_uid)

# Verify the index now exists with the new UID
renamed_index = client.index(new_uid)
info = renamed_index.fetch_info()
assert info.uid == new_uid
assert renamed_index.get_primary_key() == "objectID"


@pytest.mark.usefixtures("indexes_sample")
def test_index_update_without_params(client):
"""Test updating primary key and renaming an index together."""
index = client.index(common.INDEX_UID)
with pytest.raises(ValueError) as exc:
index.update()

assert "primary_key" in str(exc.value) or "new_uid" in str(exc.value)