Skip to content

Conversation

@jawad-khan
Copy link
Contributor

@jawad-khan jawad-khan commented Dec 3, 2025

Related issue

Fixes #1168

What does this PR do?

Update Index APIs to Support customMetadata

This PR updates the index-related APIs in the Python SDK to align with recent Meilisearch server changes and adds support for the new customMetadata field.

Key Updates

  • Added customMetadata support across index creation and update methods.

  • Synced request/response structures with the latest Meilisearch index API.

  • ...

PR checklist

Please check if your PR fulfills the following requirements:

  • Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
  • Have you read the contributing guidelines?
  • Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!

Summary by CodeRabbit

  • New Features

    • Document operations (add, update, delete; single and batched) accept an optional metadata value that is attached to the created task and returned in task info for easier tracking.
  • Tests

    • Test suite updated to supply metadata and verify it is propagated and exposed on returned task information after operations.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 3, 2025 12:57
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds an optional metadata parameter across index document methods, threads it into URL construction as customMetadata query param, and surfaces it on returned Task objects via a new customMetadata field. Tests updated to pass and assert this metadata.

Changes

Cohort / File(s) Summary
Index API methods
meilisearch/index.py
Added metadata: Optional[str] = None to public document methods (add/update/delete, batch and raw/CSV/NDJSON variants). metadata is propagated into _build_url so customMetadata=<value> is appended to request URLs when provided.
Task model
meilisearch/models/task.py
Added customMetadata: Optional[str] = None field to Task to capture server-returned metadata.
Tests
tests/index/test_index_document_meilisearch.py
Updated tests to pass metadata="Test metadata" to operations and assert the returned TaskInfo has customMetadata set accordingly.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Index as Index API
  participant HTTP as HTTP Layer
  participant Server as Meilisearch Server
  participant TaskModel as Task parser

  rect rgb(240,248,255)
  Client->>Index: call add_documents(..., metadata="Test metadata")
  Note right of Index: metadata threaded\nthrough method stack
  end

  Index->>Index: _build_url(..., metadata="Test metadata")
  Index->>HTTP: POST /indexes/{uid}/documents?customMetadata=Test%20metadata + body
  HTTP->>Server: HTTP request
  Server-->>HTTP: 202 Accepted (task JSON with customMetadata)
  HTTP->>Index: response
  Index->>TaskModel: parse task JSON (includes customMetadata)
  TaskModel-->>Client: TaskInfo with customMetadata
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

enhancement

Suggested reviewers

  • Strift

Poem

🐇 I hopped through lines both near and far,
Tucked a note in tasks like a tiny star.
Now every job carries a whispered thread,
A metadata message where tasks are led. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.68% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding customMetadata support across index APIs, which aligns with the core objective from linked issue #1168.
Linked Issues check ✅ Passed The PR fully addresses #1168 requirements: metadata parameter added to all document operation methods (add, update, delete), Task model updated with customMetadata field, and test cases added with metadata verification.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing customMetadata support across index APIs as specified in #1168; no unrelated modifications detected.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds support for the customMetadata field to index-related APIs in the Python SDK, aligning with recent Meilisearch server changes. The implementation adds an optional metadata parameter to all document manipulation methods (add, update, delete) that gets passed to the Meilisearch server as a query parameter.

Key changes:

  • Added customMetadata field to the Task model to capture metadata returned by the server
  • Updated all document methods in the Index class to accept an optional metadata parameter
  • Enhanced test coverage by adding metadata assertions to document operation tests

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
meilisearch/models/task.py Added customMetadata field as Optional[str] to Task model
meilisearch/index.py Added metadata parameter to all document methods (add/update/delete variants) and updated URL building logic to include customMetadata as a query parameter
tests/index/test_index_document_meilisearch.py Updated tests to pass metadata parameter and assert that customMetadata is persisted on task objects

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

self,
documents: Sequence[Mapping[str, Any]],
batch_size: int = 1000,
primary_key: Optional[str] = None,
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

Inconsistent API design: In add_documents_in_batches, serializer is a keyword-only argument (line 521-522 uses *,), but in this method it's not keyword-only. For consistency, consider adding *, before serializer on line 906 to make it keyword-only, or update add_documents_in_batches to match this signature. The new metadata parameter should also be keyword-only to match the pattern in add_documents_in_batches.

Suggested change
primary_key: Optional[str] = None,
primary_key: Optional[str] = None,
*,

Copilot uses AI. Check for mistakes.
index.wait_for_task(response.task_uid)
response = index.delete_documents(filter="genre=action", metadata="Test metadata")
task = index.wait_for_task(response.task_uid)
task.customMetadata = "Test metadata"
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

This line should be an assertion (assert task.customMetadata == "Test metadata") instead of an assignment. Unlike all other test cases in this file, this line assigns a value instead of verifying it, which means the test isn't actually validating that the metadata was properly persisted.

Suggested change
task.customMetadata = "Test metadata"
assert task.customMetadata == "Test metadata"

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
meilisearch/index.py (4)

601-634: Inconsistent parameter style: metadata is positional here but keyword-only in similar methods.

In add_documents, add_documents_in_batches, and add_documents_json, the metadata parameter is keyword-only (after *). However, in add_documents_csv, it's a regular positional parameter.

For API consistency, consider making metadata keyword-only:

 def add_documents_csv(
     self,
     str_documents: bytes,
     primary_key: Optional[str] = None,
     csv_delimiter: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

636-666: Same inconsistency: metadata should be keyword-only for consistency.

 def add_documents_ndjson(
     self,
     str_documents: bytes,
     primary_key: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

751-781: Same inconsistency: metadata should be keyword-only.

 def update_documents_ndjson(
     self,
     str_documents: str,
     primary_key: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

820-853: Same inconsistency: metadata should be keyword-only.

 def update_documents_csv(
     self,
     str_documents: str,
     primary_key: Optional[str] = None,
     csv_delimiter: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fdcb7b and a03eff0.

📒 Files selected for processing (3)
  • meilisearch/index.py (37 hunks)
  • meilisearch/models/task.py (1 hunks)
  • tests/index/test_index_document_meilisearch.py (15 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/index/test_index_document_meilisearch.py (1)
meilisearch/index.py (14)
  • add_documents (479-514)
  • update (108-152)
  • add_documents_in_batches (516-562)
  • add_documents_json (564-599)
  • update_documents (714-749)
  • update_documents_json (783-818)
  • update_documents_in_batches (901-946)
  • delete_document (948-975)
  • delete_documents (978-1030)
  • delete_all_documents (1032-1055)
  • add_documents_csv (601-634)
  • update_documents_csv (820-853)
  • add_documents_ndjson (636-666)
  • update_documents_ndjson (751-781)
meilisearch/index.py (2)
meilisearch/_httprequests.py (2)
  • put (120-140)
  • post (98-108)
meilisearch/models/task.py (1)
  • TaskInfo (79-108)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (31)
meilisearch/models/task.py (1)

25-25: LGTM - customMetadata field added to Task model.

The field correctly uses Optional[str] and follows the existing CamelBase naming convention for API compatibility.

tests/index/test_index_document_meilisearch.py (18)

31-40: LGTM - Test correctly verifies metadata propagation.


65-74: LGTM - Batch test correctly verifies metadata on each task.


112-120: LGTM - JSON serializer test with metadata verification.


129-140: LGTM - Raw documents test with metadata verification.


149-155: LGTM - Update documents test with metadata.


177-185: LGTM - Update documents JSON test with metadata.


194-205: LGTM - Update documents raw test with metadata.


393-398: LGTM - Update documents test with metadata.


423-432: LGTM - Update documents in batches test with metadata.


440-444: LGTM - Delete document test with metadata.


455-459: LGTM - Delete documents by ID test with metadata.


486-490: LGTM - Delete all documents test with metadata.


499-503: LGTM - Add documents CSV test with metadata.


525-530: LGTM - Update documents CSV test with metadata.


551-556: LGTM - Add documents JSON test with metadata.


563-567: LGTM - Update documents JSON test with metadata.


575-579: LGTM - Add documents NDJSON test with metadata.


587-592: LGTM - Update documents NDJSON test with metadata.

meilisearch/index.py (12)

479-514: LGTM - add_documents method correctly supports metadata parameter.

The metadata is properly threaded through to _build_url and documented in the docstring.


516-562: LGTM - add_documents_in_batches correctly propagates metadata to each batch.


564-599: LGTM - add_documents_json correctly propagates metadata.


668-712: LGTM - add_documents_raw correctly implements metadata as keyword-only.


714-749: LGTM - update_documents correctly implements metadata.


783-818: LGTM - update_documents_json correctly implements metadata as keyword-only.


855-899: LGTM - update_documents_raw correctly implements metadata as keyword-only.


901-946: LGTM - update_documents_in_batches correctly propagates metadata.

Note: The parameter style follows the existing pattern for this method (positional optional parameters), though it differs from add_documents_in_batches which uses keyword-only parameters. This is a pre-existing inconsistency.


948-975: LGTM - delete_document correctly implements metadata with URL encoding.


977-1030: LGTM - delete_documents correctly handles metadata in both the ids and filter branches.


1032-1055: LGTM - delete_all_documents correctly implements metadata.


2430-2445: LGTM - _build_url correctly centralizes the metadata query parameter construction.

Good approach to centralize the metadatacustomMetadata mapping in the URL builder.

@jawad-khan
Copy link
Contributor Author

@Strift Tests are failing because sharding require Enterprose addition now. Should we adjust test cases or somehow we can skip this check.

@jawad-khan
Copy link
Contributor Author

@Strift Please re trigger test cases.

@jawad-khan jawad-khan force-pushed the jawad/update-index-apis branch from 690ec39 to f27c052 Compare December 16, 2025 20:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
meilisearch/index.py (1)

901-908: Inconsistent API design: serializer and metadata should be keyword-only.

Unlike add_documents_in_batches (line 521-523), this method does not use *, to make serializer and metadata keyword-only. This was flagged in a prior review.

Apply this diff for consistency:

 def update_documents_in_batches(
     self,
     documents: Sequence[Mapping[str, Any]],
     batch_size: int = 1000,
     primary_key: Optional[str] = None,
+    *,
     serializer: Optional[Type[JSONEncoder]] = None,
     metadata: Optional[str] = None,
 ) -> List[TaskInfo]:
🧹 Nitpick comments (4)
meilisearch/index.py (4)

601-634: Inconsistent API design: metadata should be keyword-only.

In add_documents_csv, metadata is a positional parameter, but in similar methods like add_documents and add_documents_json, metadata is keyword-only (placed after *,). This inconsistency can lead to confusing API usage.

Apply this diff for consistency:

 def add_documents_csv(
     self,
     str_documents: bytes,
     primary_key: Optional[str] = None,
     csv_delimiter: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

636-666: Inconsistent API design: metadata should be keyword-only.

Same issue as add_documents_csv - for consistency with other methods, metadata should be keyword-only.

Apply this diff:

 def add_documents_ndjson(
     self,
     str_documents: bytes,
     primary_key: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

751-781: Inconsistent API design: metadata should be keyword-only.

For consistency with update_documents and update_documents_json, make metadata keyword-only.

Apply this diff:

 def update_documents_ndjson(
     self,
     str_documents: str,
     primary_key: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:

820-853: Inconsistent API design: metadata should be keyword-only.

For consistency, make metadata keyword-only.

Apply this diff:

 def update_documents_csv(
     self,
     str_documents: str,
     primary_key: Optional[str] = None,
     csv_delimiter: Optional[str] = None,
+    *,
     metadata: Optional[str] = None,
 ) -> TaskInfo:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 690ec39 and f27c052.

📒 Files selected for processing (3)
  • meilisearch/index.py (37 hunks)
  • meilisearch/models/task.py (1 hunks)
  • tests/index/test_index_document_meilisearch.py (15 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • meilisearch/models/task.py
🧰 Additional context used
🧬 Code graph analysis (1)
meilisearch/index.py (3)
meilisearch/_httprequests.py (3)
  • put (120-140)
  • delete (142-147)
  • post (98-108)
meilisearch/models/task.py (1)
  • TaskInfo (79-108)
meilisearch/client.py (1)
  • index (231-247)
🔇 Additional comments (30)
tests/index/test_index_document_meilisearch.py (19)

31-40: LGTM - metadata propagation test looks correct.

The test properly verifies that the customMetadata parameter is passed through add_documents and returned on the completed task.


57-76: LGTM - batch metadata propagation test is thorough.

The test correctly verifies that customMetadata is propagated for each batch task in add_documents_in_batches.


106-120: LGTM - JSON serializer with metadata test is correct.


123-140: LGTM - raw document addition with metadata test is correct.


143-155: LGTM - update documents with metadata test is correct.


171-185: LGTM - update documents JSON with metadata test is correct.


188-205: LGTM - update documents raw with metadata test is correct.


386-408: LGTM - update single document with metadata test is correct.


415-434: LGTM - update documents in batches with metadata test is correct.


437-447: LGTM - delete single document with metadata test is correct.


450-464: LGTM - delete documents by ID with metadata test is correct.


467-480: LGTM - delete documents with filter and metadata test is correct.

The previously reported assignment bug on line 475 has been addressed.


483-493: LGTM - delete all documents with metadata test is correct.


496-506: LGTM - add documents CSV with metadata test is correct.


522-531: LGTM - update documents CSV with metadata test is correct.


548-557: LGTM - add documents JSON file with metadata test is correct.


560-569: LGTM - update documents JSON file with metadata test is correct.


572-581: LGTM - add documents NDJSON with metadata test is correct.


584-593: LGTM - update documents NDJSON with metadata test is correct.

meilisearch/index.py (11)

948-975: LGTM - delete_document metadata implementation is correct.

The inline URL construction with parse.urlencode properly handles the customMetadata query parameter.


1010-1030: LGTM - delete_documents metadata handling is correct.

Both the deprecated ids path and the filter path correctly append the customMetadata query parameter when provided.


1032-1055: LGTM - delete_all_documents metadata implementation is correct.


2430-2445: LGTM - _build_url metadata handling is correct.

The implementation properly adds customMetadata to the query parameters only when metadata is provided, and uses parse.urlencode for proper URL encoding.


479-514: LGTM - add_documents metadata implementation is correct.

The metadata parameter is properly defined as keyword-only and correctly passed to _build_url.


516-562: LGTM - add_documents_in_batches metadata propagation is correct.

Metadata is properly propagated to each batch call.


564-599: LGTM - add_documents_json metadata propagation is correct.


668-712: LGTM - add_documents_raw metadata implementation is correct.


714-749: LGTM - update_documents metadata implementation is correct.


783-818: LGTM - update_documents_json metadata propagation is correct.


855-899: LGTM - update_documents_raw metadata implementation is correct.

@jawad-khan jawad-khan force-pushed the jawad/update-index-apis branch from f27c052 to 7cbc800 Compare January 1, 2026 10:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
meilisearch/index.py (1)

901-908: Inconsistent API design: serializer should be keyword-only.

In add_documents_in_batches (line 521-522), serializer and metadata are keyword-only arguments (preceded by *,), but here they're positional. This inconsistency could confuse users.

🔎 Proposed fix for consistent keyword-only arguments
 def update_documents_in_batches(
     self,
     documents: Sequence[Mapping[str, Any]],
     batch_size: int = 1000,
     primary_key: Optional[str] = None,
+    *,
     serializer: Optional[Type[JSONEncoder]] = None,
     metadata: Optional[str] = None,
 ) -> List[TaskInfo]:
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f27c052 and 7cbc800.

📒 Files selected for processing (3)
  • meilisearch/index.py
  • meilisearch/models/task.py
  • tests/index/test_index_document_meilisearch.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • meilisearch/models/task.py
🧰 Additional context used
🧬 Code graph analysis (2)
tests/index/test_index_document_meilisearch.py (3)
meilisearch/index.py (14)
  • add_documents (479-514)
  • update (108-152)
  • wait_for_task (261-288)
  • add_documents_in_batches (516-562)
  • add_documents_json (564-599)
  • update_documents (714-749)
  • update_documents_json (783-818)
  • update_documents_in_batches (901-946)
  • delete_document (948-975)
  • delete_documents (978-1030)
  • delete_all_documents (1032-1055)
  • add_documents_csv (601-634)
  • update_documents_csv (820-853)
  • update_documents_ndjson (751-781)
meilisearch/models/task.py (1)
  • TaskInfo (79-108)
meilisearch/task.py (1)
  • wait_for_task (174-212)
meilisearch/index.py (3)
meilisearch/_httprequests.py (3)
  • put (120-140)
  • delete (142-147)
  • post (98-108)
meilisearch/models/task.py (1)
  • TaskInfo (79-108)
meilisearch/client.py (1)
  • index (231-247)
🔇 Additional comments (21)
tests/index/test_index_document_meilisearch.py (14)

31-40: LGTM!

Test correctly passes metadata and verifies it's returned in the task's customMetadata field.


65-74: LGTM!

Test verifies metadata propagation for each batch task correctly.


112-120: LGTM!

Correct metadata assertion for JSON document addition with custom serializer.


129-140: LGTM!

Correct metadata assertion for raw document addition.


149-155: LGTM!

Correct metadata assertion for document update with custom serializer.


177-185: LGTM!

Correct metadata assertion for JSON document update.


194-205: LGTM!

Correct metadata assertion for raw document update.


393-398: LGTM!

Correct metadata assertion for document update.


423-432: LGTM!

Correct metadata verification for batch document updates.


440-444: LGTM!

Correct metadata assertion for single document deletion.


455-459: LGTM!

Correct metadata assertion for batch document deletion by ID.


473-476: LGTM!

The previously flagged assignment bug has been correctly fixed to use assertion (==).


486-490: LGTM!

Correct metadata assertion for delete all documents operation.


496-593: LGTM!

All CSV, JSON, and NDJSON test variants correctly pass metadata and verify customMetadata in task responses.

meilisearch/index.py (7)

2430-2445: LGTM!

The _build_url helper correctly includes customMetadata in query parameters when metadata is provided, using proper URL encoding.


479-562: LGTM!

Metadata parameter correctly added to add_documents and add_documents_in_batches with proper keyword-only enforcement and propagation to URL building.


564-712: LGTM!

All add_documents_* variants correctly accept and propagate the metadata parameter through to _build_url.


948-975: LGTM!

The delete_document method correctly appends customMetadata as a query parameter when metadata is provided.


1015-1029: LGTM!

Both the deprecated ids path and the filter path correctly include customMetadata in the URL when metadata is provided.


1032-1055: LGTM!

The delete_all_documents method correctly includes customMetadata in the URL when provided.


751-899: LGTM!

All update_documents_* variants correctly accept and propagate the metadata parameter through to _build_url.

@jawad-khan
Copy link
Contributor Author

@Strift This is ready from my side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v1.26] Add tasks custom metadata

1 participant