fix: pagination error when paginatedField is not _id#374
Conversation
WalkthroughTracks whether Sequence DiagramsequenceDiagram
participant Client
participant Find as find()
participant Sanitize as sanitizeParams()
participant DB as Database
participant Response
Client->>Find: Request (paginatedField != '_id', projection excludes _id)
activate Find
Note over Find: Record whether `_id` was requested originally
Find->>Sanitize: params + projection
activate Sanitize
rect rgb(200,220,255)
Note over Sanitize: If secondary sort on paginatedField, ensure `_id` is added for cursor (internal)
Sanitize->>Sanitize: Add `_id` to projection if absent
end
Sanitize-->>Find: Modified params (with `_id`)
deactivate Sanitize
Find->>DB: Query including `_id`
DB-->>Find: Rows with `_id`
rect rgb(220,200,255)
Note over Find: If `_id` wasn't originally requested and paginatedField != '_id'
Find->>Find: Strip `_id` from response rows
end
Find-->>Response: Paginated results (without `_id` if originally excluded)
deactivate Find
Response-->>Client: Return page + next cursor
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
🔇 Additional comments (1)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
test/find.test.ts (1)
1393-1441: Good test coverage for the core bug scenario.This test effectively validates the fix for pagination with custom
paginatedFieldand projection excluding_id. It confirms that:
- Pagination works across multiple pages
_idis correctly excluded from results when not requestedhasNextlogic remains correctConsider adding test coverage for:
- Backward pagination using
previousparameter- Pagination using
after/beforeparameters with the same scenarioThis would ensure the fix works correctly in all pagination directions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
src/find.ts(2 hunks)src/utils/sanitizeParams.ts(1 hunks)test/find.test.ts(1 hunks)
🔇 Additional comments (4)
src/utils/sanitizeParams.ts (1)
105-111: LGTM! Clear fix for cursor encoding.The safeguard correctly ensures
_idis included in projections when using a non-_idpaginated field, which is necessary for proper cursor tuple encoding. The comment clearly explains the rationale and references the encoding location.src/find.ts (3)
63-67: LGTM! Proper state tracking before modification.The code correctly captures whether
_idwas originally requested beforesanitizeParamsmodifies the projection. The timing and logic are sound.
120-127: LGTM! Correct cleanup of internally-added field.The conditional removal properly strips
_idfrom results when it was added internally for cursor encoding but not requested by the user. The logic correctly complements the safeguard insanitizeParams.
69-76: The original review comment is incorrect - the fix already applies to the aggregate path.The cleanup logic at lines 122-127 (lines that remove unwanted
_idfrom results) is outside and after the if/else block, so it processes results from both theaggregate()call (line 69-76) and thefind()path (line 77-119). The variablesoriginalFieldsIncludedIdandpaginatedFieldare also set before the conditional, ensuring the logic works for both code paths.The
shouldRemoveIdFromResponsecondition correctly evaluates for results returned fromaggregate(), removing the injected_idwhen appropriate.
When paginatedField !== '_id', cursors must be encoded as [value, _id] tuples. Without _id in projection, cursors were encoded as strings, causing pagination to fail on subsequent pages with "op is not iterable" error.
28ba215 to
b9c6dca
Compare
|
🎉 This PR is included in version 9.1.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
📚 Context/Description Behind The Change
Pagination breaks when using
paginatedField !== '_id'with projections that exclude_id.The Bug:
sanitizeParamssets_id: 0by defaultpaginatedField !== '_id', cursors must encode as[paginatedFieldValue, _id]tuples_idin results, cursor encodes as string instead of tupleTypeError: op is not iterableThe Fix:
_id: 0to_id: 1when secondary sort is needed_idfrom final results if user didn't request itDeeper explanation for reviewers
The bug occurs in two places in
query.ts:Place 1: Cursor Encoding (Line 79-81)
Place 2: Cursor Destructuring (Line 174)
Bug: When
opis a string like"my_id_2", JavaScript destructures it as an iterable of characters:["m", "y"], causing:Id < "m"instead ofId < "my_id_2")🚨 Potential Risks & What To Monitor After Deployment
Low risk - fix restores expected behavior for broken edge case. Monitor for:
_idfield in projections_idappearing in results (should not happen - test coverage added)🧑🔬 How Has This Been Tested?
🚚 Release Plan
Standard release - no special deployment steps needed.