简体   繁体   中英

MongoDB pagination using cursors without sorting

When looking for pagination techniques on the internet, one usually finds two ways:

  • Offset-based pagination:
Collection.find(
  { where_this: "equals that" },
  { skip: 15, limit: 5 }
) 
  • Cursor-based pagination:
Collection.find(
  { where_this: "equals that", _id: { $gt: cursor }},
  { sort: { _id: 1 }}
) 

But is there a way to have cursor-based pagination without sorting the collection according to that cursor? Like, telling Mongo "Alright, I want the 5 next items after that _id , no matter in which order the _ids are, just give me 5 items after you see that _id ". Something along those lines:

Collection.find(
  { where_this: "equals that", _id: { $must_come_after: cursor }},
  { sort: { other_field: 1 }}
) 

It is not always possible to use the field you're sorting with as the cursor. First of all, because these fields can be of different types and you might allow your app users to sort, for example, tables as they please. With a strongly-typed API framework like GraphQL, this would be a mess to handle. Secondly, you could have two or more equal values for that field following each other in the sorted collection. If your pages split in the middle, asking for the next page will either give you duplicates or ignore items.

Is there a way to do that? How is it usually done to allow custom sorting fields without offset-based pagination? Thanks.

When we talk about "paginating a result set", the implicit assumption is that the result set stays the same throughout the process. In order for the result set to stay the same, it must normally be sorted. Without specifying an order, the database is free to return the documents in any order, and this order may change from one retrieval to the next. Reordering of documents that a user is paginating through creates a poor user experience.

you could have two or more equal values for that field following each other in the sorted collection. If your pages split in the middle, asking for the next page will either give you duplicates or ignore items.

The database can return the documents which compare equal in any order, and this order can change between adjacent queries. This is why when sorting on a field that has a low cardinality, it is a good idea to add another field with a high cardinality to the sort expression to ensure the documents are returned in a stable order.

But is there a way to have cursor-based pagination without sorting the collection according to that cursor?

You can encode offset in a cursor identifier and use skip/limit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM