Mango Query Pagination with Bookmarks: Handling Index Rebuilds
0 reputation · 10 Dec 2022, 13:59 UTC
0 reputation · 10 Dec 2022, 13:59 UTC
When using a Mango selector to retrieve a large collection, the limit and bookmark fields allow the client to iterate through results without using skip. The bookmark is a cursor that references a specific point in the index, enabling efficient forward paging.
In a dynamic database, indexes may be rebuilt automatically or manually. It is unclear whether a bookmark that was issued before an index rebuild remains valid afterward, and if not, how the client should detect and recover from that situation.
While pagination is in progress, new documents may be inserted or existing ones deleted. The interaction between these changes and the bookmark’s position may affect the continuity of results, especially when the index is rebuilt in the middle of a paging session.
skip or startkey to mitigate issues caused by concurrent index changes?33275 reputation · 10 Dec 2022, 17:38 UTC
A Mango bookmark is an opaque cursor tied to the specific state of an index scan. When an index is rebuilt—whether manually via the _index endpoint or automatically by the database—the bookmark is invalidated. Because the underlying index structure is replaced, the previous position no longer exists. The server typically responds with an error (such as HTTP 400 or 500) or an empty result set, signaling the client to restart pagination from the beginning.
It is important to distinguish between a full index rebuild and concurrent document modifications:
Clients should implement a recovery loop to handle stale bookmarks. Monitor for the following responses:
docs array: If total_rows is greater than zero but the docs array is empty, the bookmark may have pointed to a position that no longer exists.Upon detecting these, the client should discard the current bookmark and re-issue the original query starting from the first page.
bookmark with skip. Using skip forces the server to scan through discarded records, negating the performance benefits of the bookmark and creating unpredictable offsets.To verify this behavior in a development environment (e.g., CouchDB 3.x), execute the following sequence:
# 1. Fetch the first page to obtain a bookmark
curl -X POST http://localhost:5984/db/_find -d '{"selector":{"type":"test"},"limit":10}'
# 2. Manually trigger an index rebuild
curl -X POST http://localhost:5984/db/_index -d '{"ddoc":"test-design","name":"test-index","type":"json","def":{"fields":[{"type":"asc"}]}}'
# 3. Attempt to use the bookmark from step 1
curl -X POST http://localhost:5984/db/_find -d '{"selector":{"type":"test"},"limit":10,"bookmark":"OLD_BOOKMARK_VALUE"}'
If you encounter a specific error code not listed here, please provide the response body for further analysis.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.