Skip to content

Conversation

@Ritinpaul
Copy link

@Ritinpaul Ritinpaul commented Sep 28, 2025

Pull Request

Related issue

Fixes #1996

What does this PR do?

  • Adds support for the sort parameter in the documents API (index.search).
  • Updates the SearchParams type to include sort: string[].
  • Ensures that the sort parameter is correctly forwarded to the Meilisearch server.
  • Adds test cases for single-field and multi-field sorting.
  • Updates documentation and examples to include usage of the sort option.

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?

Thanks a lot for reviewing this PR!

Summary by CodeRabbit

  • New Features

    • Fetch documents with sorting support, including multi-field sort and recognition of sort in newer server versions.
    • Graceful handling of empty sort arrays, returning default order.
  • Documentation

    • Added code samples demonstrating single- and multi-field document sorting.
  • Tests

    • Added comprehensive tests for sorting (single, multi-field, empty, invalid), index renaming, and index swapping; minor test cleanups.
  • Chores

    • Increased test client wait timeout for more reliable runs.

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

@coderabbitai
Copy link

coderabbitai bot commented Sep 28, 2025

Walkthrough

Adds optional sort support to the documents API, normalizes params in getDocuments to omit empty sort arrays, extends types (DocumentsQuery.sort, IndexOptions.uid?, SearchResponse.queryVector?), adds code samples, and introduces tests for sorting, empty-sort handling, non-sortable errors, index rename via update, and swapIndexes with rename.

Changes

Cohort / File(s) Summary of changes
Documents API logic
src/indexes.ts
getDocuments now copies input params to normalizedParams, removes sort when it is an empty array, and uses normalizedParams for GET/POST documents endpoints; JSDoc updated to mention sort.
Type updates
src/types/types.ts
Added DocumentsQuery.sort?: string[] (format attribute:direction), IndexOptions.uid?: string, and SearchResponse.queryVector?: number[].
Code samples
.code-samples.meilisearch.yaml
Added samples get_documents_sort_1 (sort release_date:desc) and get_documents_sort_multiple_1 (sort rating:desc, release_date:asc).
Document sorting tests
tests/documents.test.ts
New tests covering single-field sort, multi-field sort, empty sort: [] behavior, and error when sorting by a non-sortable attribute.
Index rename & swap tests
tests/index.test.ts, tests/client.test.ts
Added tests for renaming an index via update (changing UID) and swapping indexes with rename: true, asserting task.type === "indexSwap" and swap details.
Test utils update (timeouts)
tests/utils/meilisearch-test-utils.ts
Added timeout: 60_000 to defaultWaitOptions passed to MeiliSearch client instances.
Minor test cleanup
tests/get_search.test.ts
Removed a redundant comment; no behavior change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Application
  participant SDK as SDK.getDocuments
  participant MS as Meilisearch Server

  App->>SDK: getDocuments(indexUid, params { limit, fields, sort?, ... })
  SDK->>SDK: normalizedParams = { ...params }
  alt sort is empty array
    SDK->>SDK: delete normalizedParams.sort
  end

  alt POST /documents/fetch used
    SDK->>MS: POST /indexes/:uid/documents/fetch body: normalizedParams
    MS-->>SDK: 200 Documents (sorted if requested)
  else GET /documents used
    SDK->>MS: GET /indexes/:uid/documents?{normalizedParams}
    MS-->>SDK: 200 Documents (sorted if requested)
  end

  SDK-->>App: Documents list

  note over MS,SDK: If attribute not sortable -> 400 "Attribute `...` is not sortable"
  MS-->>SDK: 400 Error
  SDK-->>App: Propagate error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to getDocuments param normalization and all call-sites (GET vs POST).
  • Verify new sort typing and JSDoc align with API expectations and examples.
  • Review new tests for flakiness and setup/teardown correctness (sortable attribute enabling).
  • Confirm timeout addition in test utils doesn't mask long-running failures.

Possibly related PRs

  • Fix index swaps types #2000 — Modifies index-swap behavior and tests; directly relates to the added swapIndexes test asserting rename: true.

Suggested labels

maintenance

Suggested reviewers

  • curquiza
  • flevi29

Poem

I hopped through indexes, tidy and spry,
Sorted by date and rating high.
When UIDs change and swaps collide,
I trimmed empty sorts and kept things wide.
Carrots for tests — a joyful stride. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Most changes are directly related to the sort parameter feature. However, some modifications appear tangentially related: uid property addition to IndexOptions, queryVector to SearchResponse, index swap tests, and index rename tests are not directly required by the sort API requirements. Review and clarify whether uid, queryVector, swap index tests, and index rename tests are necessary for the sort parameter feature or should be in a separate PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add support for sort parameter in documents API' clearly and accurately describes the main change in the changeset.
Linked Issues check ✅ Passed All coding requirements from issue #1996 are met: the sort parameter is added to DocumentsQuery type, getDocuments implementation forwards the sort parameter, and comprehensive test coverage is included.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09ce73d and 435ae6d.

📒 Files selected for processing (8)
  • .code-samples.meilisearch.yaml (1 hunks)
  • src/indexes.ts (1 hunks)
  • src/types/types.ts (3 hunks)
  • tests/client.test.ts (2 hunks)
  • tests/documents.test.ts (1 hunks)
  • tests/get_search.test.ts (0 hunks)
  • tests/index.test.ts (1 hunks)
  • tests/utils/meilisearch-test-utils.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • tests/get_search.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/utils/meilisearch-test-utils.ts
  • src/indexes.ts
  • src/types/types.ts
🧰 Additional context used
🧬 Code graph analysis (3)
tests/documents.test.ts (1)
tests/utils/meilisearch-test-utils.ts (2)
  • dataset (225-225)
  • Book (201-207)
tests/index.test.ts (1)
src/types/types.ts (2)
  • ErrorStatusCode (843-1203)
  • ErrorStatusCode (1205-1206)
tests/client.test.ts (2)
tests/utils/meilisearch-test-utils.ts (1)
  • getClient (222-222)
src/types/task-and-batch.ts (1)
  • IndexSwap (109-112)
🔇 Additional comments (3)
tests/index.test.ts (1)

295-314: LGTM! Well-structured test for index renaming.

The test correctly verifies both the negative case (old UID no longer exists) and the positive case (new UID is accessible), providing comprehensive coverage of the rename functionality.

.code-samples.meilisearch.yaml (1)

56-63: LGTM! Clear examples demonstrating the sort parameter.

The code samples correctly illustrate both single-field and multi-field sorting for the getDocuments API, using the proper array-of-strings format with field:direction syntax.

tests/documents.test.ts (1)

261-342: LGTM! Comprehensive test coverage for document sorting.

The four new tests provide excellent coverage:

  • Single-field sort verifies basic ascending order
  • Multi-field sort uses custom documents with duplicate primary values to ensure secondary sort is respected
  • Empty sort array tests the edge case gracefully
  • Non-sortable attribute test ensures proper error handling

The multi-field test particularly addresses the previous concern by creating ties on the primary sort key and asserting the secondary sort order within those ties.


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

@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: 2

🧹 Nitpick comments (1)
tests/documents.test.ts (1)

292-301: Strengthen multi-field sort assertion

We’re aiming to verify forwarding of the entire sort array, yet this check only confirms the first entry (id:desc). Because id stays unique in dataset, a regression that strips the secondary key (title:asc) would still pass. Please reshape the test data or expectations so the first sort key contains duplicates (e.g., sort primarily on genre) and assert the order within those duplicates; that way the test actually fails if we drop the second key.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4f7c885 and 7f161f0.

📒 Files selected for processing (9)
  • .code-samples.meilisearch.yaml (2 hunks)
  • package.json (1 hunks)
  • src/indexes.ts (1 hunks)
  • src/types/types.ts (3 hunks)
  • tests/client.test.ts (1 hunks)
  • tests/documents.test.ts (1 hunks)
  • tests/get_search.test.ts (0 hunks)
  • tests/index.test.ts (1 hunks)
  • tests/utils/meilisearch-test-utils.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • tests/get_search.test.ts
🧰 Additional context used
🧬 Code graph analysis (5)
tests/client.test.ts (3)
tests/utils/meilisearch-test-utils.ts (1)
  • getClient (369-369)
src/meilisearch.ts (1)
  • index (92-94)
src/types/task_and_batch.ts (1)
  • IndexSwap (109-112)
tests/index.test.ts (1)
src/types/types.ts (2)
  • ErrorStatusCode (864-1224)
  • ErrorStatusCode (1226-1227)
tests/utils/meilisearch-test-utils.ts (1)
src/meilisearch.ts (1)
  • MeiliSearch (49-570)
tests/documents.test.ts (2)
tests/env/node/getting_started.cjs (1)
  • dataset (12-19)
tests/utils/meilisearch-test-utils.ts (2)
  • dataset (372-372)
  • Book (339-345)
src/indexes.ts (1)
src/types/types.ts (1)
  • ResourceResults (129-132)

Comment on lines 34 to 35
rename_an_index_1: |-
client.updateIndex('INDEX_A', { indexUid: 'INDEX_B' })
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix the rename example to use the correct payload key

updateIndex expects the new identifier under uid, not indexUid. Shipping this sample as-is will make readers copy a snippet that the server rejects.(meilisearch.com)

-  client.updateIndex('INDEX_A', { indexUid: 'INDEX_B' })
+  client.updateIndex('INDEX_A', { uid: 'INDEX_B' })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rename_an_index_1: |-
client.updateIndex('INDEX_A', { indexUid: 'INDEX_B' })
rename_an_index_1: |-
client.updateIndex('INDEX_A', { uid: 'INDEX_B' })
🤖 Prompt for AI Agents
In .code-samples.meilisearch.yaml around lines 34 to 35, the example uses an
incorrect payload key `indexUid` when calling client.updateIndex; the API
expects the new identifier under the `uid` key. Change the payload object to use
`uid: 'INDEX_B'` instead of `indexUid: 'INDEX_B'` so the sample matches the
server expectation.

Comment on lines 570 to 598
test(`${permission} key: Swap two indexes with rename`, async () => {
const client = await getClient(permission);
const originalUid1 = index.uid;
const originalUid2 = index2.uid;

await client
.index(originalUid1)
.addDocuments([{ id: 1, title: "index_1" }])
.waitTask();
await client
.index(originalUid2)
.addDocuments([{ id: 1, title: "index_2" }])
.waitTask();

const swaps: IndexSwap[] = [
{ indexes: [originalUid1, originalUid2], rename: true },
];

const resolvedTask = await client.swapIndexes(swaps).waitTask();

// Verify the swap task completed with expected details
expect(resolvedTask.type).toEqual("indexSwap");
expect(resolvedTask.details?.swaps).toEqual(swaps);
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Rename swap test should assert a successful rename

We’re pre-populating both indexes and then calling swapIndexes with rename: true, even though the API expects the second UID to be unused when you opt into rename mode. If the server rejects the rename (e.g., with index_already_exists), the test still “passes” because we only read the task type/details and never assert success or the post-rename state. Let’s stop creating the destination index ahead of time and assert that the task succeeds and that the old UID is gone while the new UID now holds the payload.(meilisearch.com)

-        await client
-          .index(originalUid2)
-          .addDocuments([{ id: 1, title: "index_2" }])
-          .waitTask();
-
         const swaps: IndexSwap[] = [
           { indexes: [originalUid1, originalUid2], rename: true },
         ];
 
         const resolvedTask = await client.swapIndexes(swaps).waitTask();
 
-        // Verify the swap task completed with expected details
-        expect(resolvedTask.type).toEqual("indexSwap");
-        expect(resolvedTask.details?.swaps).toEqual(swaps);
+        expect(resolvedTask.status).toEqual("succeeded");
+        expect(resolvedTask.type).toEqual("indexSwap");
+        expect(resolvedTask.details?.swaps).toEqual(swaps);
+        await expect(
+          client.index(originalUid1).getDocument(1),
+        ).rejects.toHaveProperty("cause.code", ErrorStatusCode.INDEX_NOT_FOUND);
+        const renamedDoc = await client.index(originalUid2).getDocument(1);
+        expect(renamedDoc.title).toEqual("index_1");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test(`${permission} key: Swap two indexes with rename`, async () => {
const client = await getClient(permission);
const originalUid1 = index.uid;
const originalUid2 = index2.uid;
await client
.index(originalUid1)
.addDocuments([{ id: 1, title: "index_1" }])
.waitTask();
await client
.index(originalUid2)
.addDocuments([{ id: 1, title: "index_2" }])
.waitTask();
const swaps: IndexSwap[] = [
{ indexes: [originalUid1, originalUid2], rename: true },
];
const resolvedTask = await client.swapIndexes(swaps).waitTask();
// Verify the swap task completed with expected details
expect(resolvedTask.type).toEqual("indexSwap");
expect(resolvedTask.details?.swaps).toEqual(swaps);
});
test(`${permission} key: Swap two indexes with rename`, async () => {
const client = await getClient(permission);
const originalUid1 = index.uid;
const originalUid2 = index2.uid;
// only populate the source index
await client
.index(originalUid1)
.addDocuments([{ id: 1, title: "index_1" }])
.waitTask();
const swaps: IndexSwap[] = [
{ indexes: [originalUid1, originalUid2], rename: true },
];
const resolvedTask = await client.swapIndexes(swaps).waitTask();
expect(resolvedTask.status).toEqual("succeeded");
expect(resolvedTask.type).toEqual("indexSwap");
expect(resolvedTask.details?.swaps).toEqual(swaps);
// originalUid1 should no longer exist
await expect(
client.index(originalUid1).getDocument(1),
).rejects.toHaveProperty("cause.code", ErrorStatusCode.INDEX_NOT_FOUND);
// new index originalUid2 should now contain the documents from originalUid1
const renamedDoc = await client.index(originalUid2).getDocument(1);
expect(renamedDoc.title).toEqual("index_1");
});
🤖 Prompt for AI Agents
In tests/client.test.ts around lines 570 to 593, the rename-swap test is
creating both source and destination indexes then calling swapIndexes with
rename:true which violates the API expectation and allows silent rejection;
remove the code that pre-creates/populates the destination index (originalUid2),
call swapIndexes with rename:true where originalUid2 is unused, await the task
and assert it succeeded (e.g., status 'succeeded'), then verify the old UID no
longer exists and the new UID contains the expected document (check the document
by id/title) to confirm the rename occurred.

@Ritinpaul Ritinpaul force-pushed the feat/documents-api-sort branch from 7f161f0 to 1a1f07f Compare September 28, 2025 11:09
Copy link

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f161f0 and 1a1f07f.

📒 Files selected for processing (4)
  • .code-samples.meilisearch.yaml (1 hunks)
  • src/indexes.ts (1 hunks)
  • src/types/types.ts (3 hunks)
  • tests/documents.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .code-samples.meilisearch.yaml
  • src/indexes.ts
  • src/types/types.ts
🧰 Additional context used
🧬 Code graph analysis (1)
tests/documents.test.ts (2)
tests/env/node/getting_started.cjs (2)
  • client (4-7)
  • dataset (12-19)
tests/utils/meilisearch-test-utils.ts (3)
  • getClient (369-369)
  • dataset (372-372)
  • Book (339-345)

@codecov
Copy link

codecov bot commented Sep 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.84%. Comparing base (4f7c885) to head (09ce73d).
⚠️ Report is 38 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2038   +/-   ##
=======================================
  Coverage   98.83%   98.84%           
=======================================
  Files          18       18           
  Lines        1549     1557    +8     
  Branches      334      338    +4     
=======================================
+ Hits         1531     1539    +8     
  Misses         18       18           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Strift Strift added the enhancement New feature or request label Dec 7, 2025
@Strift Strift force-pushed the feat/documents-api-sort branch from 09ce73d to 435ae6d Compare December 7, 2025 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[v1.16.0] Add support for sorting on the documents API

2 participants