Skip to content

Conversation

Nymuxyzo
Copy link
Contributor

@Nymuxyzo Nymuxyzo commented Aug 20, 2025

Pull Request

Related issue

Fixes #643

What does this PR do?

  • Add sort to documents 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?

Summary by CodeRabbit

  • New Features

    • Added optional sorting when retrieving documents from an index, supported with and without filters.
  • Documentation

    • Updated docs to describe the new sort option; accepts a list of attributes as an array or a comma‑separated string.
  • Tests

    • Expanded test dataset and added coverage for ascending/descending sorts, sorting combined with filters, and cases with missing fields.

Copy link

coderabbitai bot commented Aug 20, 2025

Walkthrough

Adds optional :sort support to Index#documents retrieval, including :sort in GET query or POST fetch body depending on presence of filters; tests add a document, make comment filterable, and introduce sorting test cases (asc/desc and combined with NOT EXISTS).

Changes

Cohort / File(s) Summary
Core SDK: documents sort support
lib/meilisearch/index.rb
Adds handling of :sort in documents(options = {}): includes :sort among allowed keys for GET query (Utils.parse_query keys) and for POST fetch body (Utils.filter keys). Method signature unchanged.
Tests: data and sorting scenarios
spec/meilisearch/index/documents_spec.rb
Adds document objectId: 13 (title "Zen in the Art of Archery"), adds comment to filterable attributes, and introduces sorting tests (ascending/descending by title, and sorting combined with comment NOT EXISTS). Note: sorting test blocks are duplicated in two locations within the #documents context.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Index as Index#documents
  participant API as Meilisearch API

  Client->>Index: documents(options)
  alt options includes filter
    Note right of Index: build POST body with { limit, offset, fields, filter, sort }
    Index->>API: POST /indexes/:uid/documents/fetch (body includes sort)
    API-->>Index: { hits, limit, offset, ... }
  else no filter
    Note right of Index: build GET query with { limit, offset, fields, sort }
    Index->>API: GET /indexes/:uid/documents?sort=...
    API-->>Index: { results, limit, offset, ... }
  end
  Index-->>Client: documents list
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • Add get documents by ids #632 — modifies Index#documents to accept and forward an additional option key to the documents endpoints (related change pattern).

Suggested labels

enhancement

Suggested reviewers

  • brunoocasali

Pre-merge checks (5 passed)

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title “Add documents API sort” succinctly and accurately summarizes the main change of adding sort support to the documents API without unnecessary detail or noise.
Linked Issues Check ✅ Passed The implementation updates the documents method to accept the sort parameter and includes new test cases verifying ascending and descending sorting (including filtered scenarios), fully addressing the tasks defined in issue #643.
Out of Scope Changes Check ✅ Passed All modifications, including SDK updates and accompanying tests, are focused on adding sort functionality and do not introduce unrelated features or code beyond what the linked issue specifies.
Description Check ✅ Passed The description clearly references the related issue (#643) and states that the PR adds sort support to the documents API, which aligns directly with the changes introduced in the code.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Poem

I hop through code with ears alert, 🐇
I tuck in sort and guard the field,
Titles rise or tumble neat,
A comment gone — the list repeats,
Sorted hops make tests complete. ✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 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 a74c0bd and 6ba4c1d.

📒 Files selected for processing (2)
  • lib/meilisearch/index.rb (1 hunks)
  • spec/meilisearch/index/documents_spec.rb (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/meilisearch/index.rb
  • spec/meilisearch/index/documents_spec.rb
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@Nymuxyzo
Copy link
Contributor Author

The errors are related to: #645

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: 0

🧹 Nitpick comments (3)
lib/meilisearch/index.rb (2)

76-76: Clarify the :sort option and note server version support.

Improve the inline docs with examples and an explicit version note for when Meilisearch added sort on the documents API.

-    #           :sort   - A list of attributes written as an array or as a comma-separated string (optional)
+    #           :sort   - A list of sort rules ("attribute:order"), provided as an Array or a comma-separated String (optional, Meilisearch v1.16+).

82-85: Normalize sort for POST and drop empty sort for GET to avoid sending ambiguous values.

Today:

  • POST body forwards sort as-is. If a caller passes a comma-separated String, it may or may not be accepted by the API. Normalizing to an Array makes behavior predictable.
  • GET query serializes Arrays to a comma-separated String. If the array is empty, we currently send sort= which can cause confusing behavior on older servers.

Proposed refactor: coerce POST sort to an Array when given as a String, and strip empty sort on both paths. This is backward-compatible and avoids sending meaningless parameters.

Can you confirm whether /documents/fetch accepts sort as a String? If not guaranteed across Meilisearch versions, the normalization below is safer.

       Utils.version_error_handler(__method__) do
-        if options.key?(:filter)
-          http_post "/indexes/#{@uid}/documents/fetch", Utils.filter(options, [:limit, :offset, :fields, :filter, :sort])
-        else
-          http_get "/indexes/#{@uid}/documents", Utils.parse_query(options, [:limit, :offset, :fields, :sort])
-        end
+        if options.key?(:filter)
+          body = Utils.filter(options, [:limit, :offset, :fields, :filter, :sort])
+          # Normalize POST body: accept "title:asc,title2:desc" and turn it into an Array.
+          if body[:sort].is_a?(String)
+            body[:sort] = body[:sort].split(',').map!(&:strip)
+          end
+          body.delete(:sort) if body[:sort].respond_to?(:empty?) && body[:sort].empty?
+          http_post "/indexes/#{@uid}/documents/fetch", body
+        else
+          query = Utils.parse_query(options, [:limit, :offset, :fields, :sort])
+          # Avoid sending sort= for empty arrays on older servers.
+          if query[:sort].is_a?(String) && query[:sort].empty?
+            query.delete(:sort)
+          end
+          http_get "/indexes/#{@uid}/documents", query
+        end
       end
spec/meilisearch/index/documents_spec.rb (1)

427-447: Sorting tests look solid; consider adding a GET string-form case (and POST string-form if you adopt normalization).

Current tests cover Array form for both GET and POST. To fully capture the public contract described in docs (“array or comma-separated string”), add:

  • GET with a comma-separated String.
  • Optionally POST with a String if you adopt the normalization suggested in lib/meilisearch/index.rb.
       describe 'sorts documents' do
         before do
           index.update_sortable_attributes(['title']).await
         end

         it 'get' do
           docs = index.documents(sort: ['title:asc'])
           expect(docs['results'].first).to include('objectId' => 1, 'title' => 'Alice In Wonderland')
           expect(docs['results'].last).to include('objectId' => 13, 'title' => 'Zen in the Art of Archery')

           docs = index.documents(sort: ['title:desc'])
           expect(docs['results'].first).to include('objectId' => 13, 'title' => 'Zen in the Art of Archery')
           expect(docs['results'].last).to include('objectId' => 1, 'title' => 'Alice In Wonderland')
         end
+        
+        it 'get accepts comma-separated string' do
+          docs = index.documents(sort: 'title:asc')
+          expect(docs['results'].first).to include('objectId' => 1, 'title' => 'Alice In Wonderland')
+          expect(docs['results'].last).to include('objectId' => 13, 'title' => 'Zen in the Art of Archery')
+        end

         it 'post' do
           docs = index.documents(filter: 'comment NOT EXISTS', sort: ['title:asc'])
           expect(docs['results'].first).to include('objectId' => 2, 'title' => 'Le Rouge et le Noir')
           expect(docs['results'].last).to include('objectId' => 13, 'title' => 'Zen in the Art of Archery')
         end
+
+        # Enable this only if POST normalization to Array is implemented in the SDK:
+        # it 'post accepts comma-separated string' do
+        #   docs = index.documents(filter: 'comment NOT EXISTS', sort: 'title:asc')
+        #   expect(docs['results'].first).to include('objectId' => 2, 'title' => 'Le Rouge et le Noir')
+        # end
       end
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1091577 and be3dcc8.

📒 Files selected for processing (2)
  • lib/meilisearch/index.rb (1 hunks)
  • spec/meilisearch/index/documents_spec.rb (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
lib/meilisearch/index.rb (2)
lib/meilisearch/utils.rb (2)
  • filter (44-46)
  • parse_query (48-56)
lib/meilisearch/http_request.rb (2)
  • http_post (39-51)
  • http_get (26-37)
spec/meilisearch/index/documents_spec.rb (1)
lib/meilisearch/index.rb (3)
  • update_filterable_attributes (531-534)
  • update_sortable_attributes (549-552)
  • documents (79-87)
🔇 Additional comments (2)
spec/meilisearch/index/documents_spec.rb (2)

13-13: Good addition to exercise NOT EXISTS logic.

Adding a document without a comment field is a clean way to validate comment NOT EXISTS behavior in sorting and filtering tests.


387-387: Enabling comment as filterable is necessary for the NOT EXISTS scenario.

This aligns the test setup with the filter used later and prevents false negatives.

@Nymuxyzo Nymuxyzo force-pushed the feat/documents-api-sort branch from be3dcc8 to a74c0bd Compare August 24, 2025 18:36
Copy link

codecov bot commented Aug 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (0a4833c) to head (6ba4c1d).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #646   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           10        10           
  Lines          806       806           
=========================================
  Hits           806       806           

☔ 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.

@Nymuxyzo Nymuxyzo force-pushed the feat/documents-api-sort branch from a74c0bd to 1630584 Compare September 9, 2025 10:08
@Nymuxyzo Nymuxyzo force-pushed the feat/documents-api-sort branch from 1630584 to 6ba4c1d Compare September 9, 2025 10:13
Copy link
Member

@brunoocasali brunoocasali left a comment

Choose a reason for hiding this comment

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

Thanks a lot!

bors merge

@brunoocasali brunoocasali added the enhancement New feature or request label Sep 9, 2025
Copy link
Contributor

meili-bors bot commented Sep 9, 2025

@meili-bors meili-bors bot merged commit 97c94a2 into meilisearch:main Sep 9, 2025
9 checks passed
@Nymuxyzo Nymuxyzo deleted the feat/documents-api-sort branch September 9, 2025 16:20
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