What are common methods for pagination queries in MongoDB?

There are two common pagination approaches for a user interface: infinite scrolling and ranged.

Example use case

  • Show the most recent items first.
  • Each document contains an _id field with an ObjectId value.
  • New items inserted in between pagination queries are ignored or handled separately.

Approach #1: Infinite scrolling pagination

Normally this is for an application that displays a feed or timeline. The application queries for more items when a user either scrolls or clicks next. For example:
var page_size = 30;
var latest_id = <most recent="" value="" of="" _id="">;
db.collection.find( { _id:{ '$lte' : latest_id } } )
             .limit( page_size )
             .sort( { _id: -1 } );
The example above fetches the most recent items as a batch in descending order. Note that new items that are inserted during viewing need to be handled separately.

Approach #2: Ranged pagination

Web pages that display a lot of items may provide numbered page links. The maximum number of pages typically has a reasonable upper limit beyond which users are encouraged to refine their search criteria in order to reduce the result set.
Some samples of this navigation style include:
1 2 3 .. last
first .. 3 4 5 6 7 .. last
1 .. 26 27 28 29
Each of these examples includes links for the first, last, and two pages forward and backward from the current page (highlighted in bold).
The total number of pages is estimated using a count with the query criteria. Individual pages of results are retrieved using appropriate skip and limitvalues.
For example, to jump to page current + N, where N is 0, 1 or 2 pages forward (higher number) and N is a relative number to the current page:
var page_size = 30;

// Update this value when the current page has been changed.
var current_id = <most recent="" value="" of="" _id="" (first="" page)="">;

db.collection.find( {_id: {'$lte': current_id }} )
             .skip( N * page_size )
             .limit( page_size )
             .sort( {_id: -1 } );
To jump to page current - N ; where N is 0, 1 or 2 pages backward (lesser number):
db.collection.find( {_id: {'$gt': current_id }} )
             .skip( N * page_size )
             .limit( page_size )
             .sort( {_id: -1 } );
Warning
Using skip() with large values (more than a few pages of results) is NOT recommended as the server scans the skipped range of documents in order to find the start of the requested document range. See cursor.skip behaviour.
For example, to display items in descending order when a user starts at page one:
var page_size = 30;

// The most recent value of _id on the collection
var current_id = 9000;

// if user clicks on page 3 , which is 2 pages away from current page. N = 2
db.collection.find( {_id: {'$lte': current_id }} )
             .skip( 2 * page_size )
             .limit( page_size )
             .sort( {_id: -1 } );
// Now change the current_id to the highest id returned (_id = 8040)
You could also use projection to limit the fields in the returned documents and reduce the amount of data sent over the network.

Comments