mongoose Pagination with NodeJS and MongoDB

Pagination

Pagination is a process in which a document is divided into discrete pages. In simple words, if we have a document containing a large amount of data, and we wish not to print all of it in once, we divide this data into “pages”. These pages contain data according to the limit specified. In this article, we will discuss how to use mongoose for pagination with NodeJS and MongoDB.

For example, say there is a collection containing one hundred documents. And the client is requesting these documents. Should we send all one hundred documents at once? No! it is not a good idea. Instead, we paginate it. Say, we send ten documents per request. This is called pagination. Let’s discuss pagination in MongoDB.

We will be using the postman tool for testing this route. You can download this tool from www.getpostman.com.

Pagination example

This is the players collection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{ "_id" : ObjectId("5e33fb961d45d9b08b5bc336"), "name" : "Leonel Messi" }
{ "_id" : ObjectId("5e33fb9e1d45d9b08b5bc337"), "name" : "Cristiano Ronaldo" }
{ "_id" : ObjectId("5e33fba61d45d9b08b5bc338"), "name" : "Sergio Ramos" }
{ "_id" : ObjectId("5e33fbb21d45d9b08b5bc339"), "name" : "Sadio Mane" }
{ "_id" : ObjectId("5e33fbc31d45d9b08b5bc33a"), "name" : "Kevin De Bruyne" }
{ "_id" : ObjectId("5e33fbcf1d45d9b08b5bc33b"), "name" : "Neymar Jr." }
{ "_id" : ObjectId("5e33fbe11d45d9b08b5bc33c"), "name" : "Mo Salah" }
{ "_id" : ObjectId("5e33fc041d45d9b08b5bc33d"), "name" : "Eden Hazard" }
{ "_id" : ObjectId("5e33fc2d1d45d9b08b5bc33e"), "name" : "Luis Suarez" }
{ "_id" : ObjectId("5e33fc341d45d9b08b5bc33f"), "name" : "Gareth Bale" }
{ "_id" : ObjectId("5e33fc5b1d45d9b08b5bc340"), "name" : "David De Gea" }
{ "_id" : ObjectId("5e33fc661d45d9b08b5bc341"), "name" : "Marcus Rashford" }
{ "_id" : ObjectId("5e33fd301d45d9b08b5bc342"), "name" : "David Silva" }
{ "_id" : ObjectId("5e33fd3e1d45d9b08b5bc343"), "name" : "Jon Oblak" }
{ "_id" : ObjectId("5e33fd4d1d45d9b08b5bc344"), "name" : "Paula Dybala" }
{ "_id" : ObjectId("5e33fd921d45d9b08b5bc345"), "name" : "Paul Pogba" }
{ "_id" : ObjectId("5e33fd9c1d45d9b08b5bc346"), "name" : "Mesut Ozil" }
{ "_id" : ObjectId("5e33fdb01d45d9b08b5bc347"), "name" : "Marcus Reus" }
{ "_id" : ObjectId("5e33fdcf1d45d9b08b5bc348"), "name" : "Raheem Sterling" }
{ "_id" : ObjectId("5e33fe161d45d9b08b5bc349"), "name" : "Karim Benzama" }

We can see, this collection contains the names of various footballer players. There are twenty documents in this collection. We will perform pagination on this collection by dividing it into four pages, each containing five documents.

There are various options for pagination in mongoose. We can write the code ourselves or use any external library. Here, we will go with the second option. There are quite a few libraries for pagination. We will use “mongoose-aggregate-paginate-v2”. Let’s begin by installing this library.

1
npm install mongoose-aggregate-paginate-v2

We need to import this library into the schema. This is the schema I created using mongoose.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const mongoose = require("mongoose");

const Schema = mongoose.Schema;

let player = new Schema(
  {
    name: {
      type: String
    }
  },
  {
    collection: "players"
  }
);

module.exports = mongoose.model("players", player);

Let’s import the library we just installed in this file.

1
var aggregatePaginate = require("mongoose-aggregate-paginate-v2");

Then, we need to tell mongoose that we are going to use this library with our schema.

1
player.plugin(aggregatePaginate);

Now, this is how the model looks like.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const mongoose = require("mongoose");

const Schema = mongoose.Schema;

var aggregatePaginate = require("mongoose-aggregate-paginate-v2"); //first step

let player = new Schema(
  {
    name: {
      type: String
    }
  },
  {
    collection: "players"
  }
);

player.plugin(aggregatePaginate); //second step

module.exports = mongoose.model("players", player);

The model is ready! Let’s create the route handler.

1
router.route("/paginationexample").get(function(req, res) {});

This is the route handler in which we will write the code for pagination. The library we just install provides a method called aggregatePaginate(). This method has three parameters – the aggregate query, options, and a callback function. The second parameter will decide how pagination will work. We have to pass an object as the second parameter. This object contains two properties – page and limit.

It looks something like this.

1
2
3
4
{
        page: 3,
        limit: 5
    }

This means, the third page will be returned and every page will contain as much as five documents. The first parameter is the aggregate query.

1
var aggregateQuery = player.aggregate();

And the third parameter is a callback function. This function has two parameters – an error (if any occurs) and the returning value.

Let’s add everything into the route handler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
router.route("/paginationexample").get(function(req, res) {
  var aggregateQuery = players.aggregate();

  players.aggregatePaginate(aggregateQuery, { page: 3, limit: 5 }, function(
    err,
    result
  ) {
    if (err) {
      console.err(err);
    } else {
      res.json(result);
    }
  });
});

What do you think this route handler will do when executed? It will return the third page out of the four pages. Let’s execute this using postman.

Image from Gyazo

It returns an array of objects. Let’s discuss what all of these fields denote.

docs: It contains the array of objects(documents) total does: total number of documents in the collection limit: limit per page we specified page: current page totalPages: total number of pages after pagination hasPrevPage: true if there exists a previous page, else false hasNextPage: true if there exists a next page, else false prevPage: total number of previous pages nextPage: total number of pages ahead.

Conclusion

This is how we use pagination in mongoose. As mentioned earlier, there are various ways for pagination, and according to us, this is one the easiest and simple way. The object returned contains a lot of information and this information is very efficient while working with the client-side.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.