I am Hack Sparrow
Captain of the Internets.

MongoDB Pagination – using $slice

How to implement pagination in MongoDB using $slice


Another technique of implementing pagination in MongoDB involves the use of $push and $slice. In this method, we store the documents in an array and use the $slice method to accomplish what skip()-and-limit() does, but without the overhead associated with the skip() method.

We will be using a single root document in a collection with two fields: i. an array to store the sub-documents, ii. a numerical key to store the size of the array.

// Clear the collection of any previous data and create the root document
db.companies.drop()
db.companies.insert({items:[], count:0})

// Add the sub-documents to the root document
db.companies.update({}, {$push:{items:'Google'}})
db.companies.update({}, {$set:{count:1}})
db.companies.update({}, {$push:{items:'Facebook'}})
db.companies.update({}, {$set:{count:2}})
db.companies.update({}, {$push:{items:'Apple'}})
db.companies.update({}, {$set:{count:3}})
db.companies.update({}, {$push:{items:'Microsoft'}})
db.companies.update({}, {$set:{count:4}})
db.companies.update({}, {$push:{items:'Oracle'}})
db.companies.update({}, {$set:{count:5}})
db.companies.update({}, {$push:{items:'IBM'}})
db.companies.update({}, {$set:{count:6}})
db.companies.update({}, {$push:{items:'Yahoo'}})
db.companies.update({}, {$set:{count:7}})
db.companies.update({}, {$push:{items:'HP'}})
db.companies.update({}, {$set:{count:8}})

Now observe how the $slice operator works.

db.companies.find({}, {items:{$slice:[0, 3]}})
db.companies.find({}, {items:{$slice:[3, 3]}})

From the above commands you can see, you already have pagination in place. It just needs to be made dynamic, which is accomplished thus:

var skip = NUMBER_OF_ITEMS * (PAGE_NUMBER - 1)
db.companies.find({}, {$slice:[skip, NUMBER_OF_ITEMS]})

NUMBER_OF_ITEMS is the number of items to be shown on a page
PAGE_NUMBER is the current page number

For creating the pagination navigation links, use the count field to get the number of items and the number of pages.

Notes

  1. Items are no longer root documents
  2. Need to maintain a count key
  3. Data structure clarity and logic is somewhat lost

2 Responses to “MongoDB Pagination – using $slice”

  1. lupo7 says:

    This is great thanks.
    I read all three pagination methods you re proposing (using skip, using range and this one), very good tutorials.

    The only problem I have in my implementation is that I can’t count results, and I don’t have an autoincresing id. The skip() method seems the only solution to me, but it won’t scale, so it is not a real solution.

    In your example, you ‘re counting records when inserting. But what if i have thousands of records, and I wan’t to show a different group each time. For example when I have some tags to filter the results a user needs. I don’t seem to find a way to implement this with the range, or slice method. Am I wrong?

  2. Ricardo Longa says:

    And about how to order the pagination result with slice? Any idea?

Make a Comment