DEV Community

Victor Peter
Victor Peter

Posted on

Pagination with Mongoose Paginate V2 (ExpressJS and Typescript)

Introduction

When writing a service that will gorw in terms of data (having from hundreds to thousands of records) for a collection and it will be unwise to send your user all the document each time the server ie being queried. To manage that, you have to share the documents into pages.

A page is simply a subdivision of documents from the total documents the database holds. Example if I have a collection of posts with 100 documents in it, I can paginate it by sending 20 documents per query. This means that I'll have a total of 5 pages, each with 20 posts.

A page usually has a skip which is the number of documents to skip, a limit which is the number or size of documents for the page requested. So, normally to get page 1 with 20 posts, the skip will value will be 0 and the limit value will be 20. To get page 2 the skip value will be 20 (this will skip the first 20 records) and limit will be 20.

Mongoose paginate v2

There's a better way to manage pagination on your Mongo database and that is with using the mongoose-paginate-v2 plugin.

Here are the steps to take to start using mongoose paginate v2 below.

Step 1: Install mongoose mongoose on your express project

Run the code below to install mongoose paginate v2

npm i mongoose mongoose-paginate-v2
Enter fullscreen mode Exit fullscreen mode

Step 2: Connect to mongodb

Make sure you have MongoDB installed (You can download MongoDB server for your pc here) on your PC, or you can use MongoDB Atlas as your cloud database (register for MongoDB atlas here and get your database url) if you don't want to install mongodb on your PC. You can connect to mongodb via puttig this code snippet on your project's entry point file:

mongoose
  .connect('mongodb://localhost:27017/my_test_database')
  .then(() => {
    console.log("Connected to database");
  })
  .catch((error) => {
    console.log(error);
  });
Enter fullscreen mode Exit fullscreen mode

Replace "my_test_database" with the name of the database you'll like to use. Don't worry, if the database does not exist, it will be created automatically.

Step 3: Write your schema and initialize the mongoose paginate plugin.

Next, you'll have to write a schema to use with yoir project and initalize the plugin for the collection you want to paginate using mongoose-paginate-v2. You can choose to initialize the paginate plugin only on collections that you'll like to paginate. Here is how to do it below:

import {Schema, InferSchemaType, model, PaginateModel} from "mongoose";
import paginate from "mongoose-paginate-v2";

const postSchema = new Schema({
    title: {
        type: String,
        default: 0
    },
    body: {
        type: String,
        default: 0
    }
}, {timestamps: true});

type postCollectionType = InferSchemaType<typeof postSchema>;

postSchema.plugin(paginate);

const postCollection = model<postCollectionType, PaginateModel<postCollectionType>>("posts", postSchema);

export {postCollection, postCollectionType};
Enter fullscreen mode Exit fullscreen mode

Let me explain some lines of code:

{timestamps: true}
This line is used to include the createdAt and updatedAt timestamps and update the updatedAt timestamp once there's a change to a record.

type postCollectionType = InferSchemaType<typeof postSchema>;
This line of code creates a type for my schema automatically, so I don't have to write a type or interface to use with the collection records. Easy peasy... ;)

postSchema.plugin(paginate);
This is you initializing or registering the plugin with the schema, the schema now knows that there's a paginate plugin that will handle paginating of data.

<postCollectionType, PaginateModel<postCollectionType>>
This is used to give your model the pagination type, so that yo can access properties of mongoose paginate v2 plugins.

Step 4: Query and paginate the result of your query

Here is how you can query the posts model from any of your express route.

import { Response, Router, NextFunction, Request } from "express";
import { postCollection } from "../models/postModel.ts";

const postRoutes = Router();

postRoutes.get("/posts/:page/:limit", async (req: Request, res: Response, next: NextFunction) => {
    try {

    const {page, limit} = req.params;

    const paginatedPost = await postCollection.paginate({}, {
        page,
        limit
    });

    res.send({paginatedPost});

    } catch (error) {
        next(error);
    }
});
Enter fullscreen mode Exit fullscreen mode

The endpoint

Result

{
    "paginatedPost": {
        "docs": [],
        "totalDocs": 0,
        "limit": 10,
        "totalPages": 1,
        "page": 1,
        "pagingCounter": 1,
        "hasPrevPage": false,
        "hasNextPage": false,
        "prevPage": null,
        "nextPage": null
    }
}
Enter fullscreen mode Exit fullscreen mode

docs property will be contain the records you're querying for about.
totalDocs the number of documents returned in the docs property.
limit the limit is the total number of documents you want per page.
totalPages the total number of pages available.
page the current page you're viewing.
pagingCounter I think it's same as page, I may be wrong.
hasPrevPage Boolean to indicate if the page has a previous page.
hasNextPage Boolean to indicate if the page has a next page.
prevPage null to indicate that there's no previous page.
nextPage null to indicate that there's no next page.

Conclusion

Apart from pagination, you can sort, populate, select, etc the type of data you want to paginate, you can read more and see more example of how to use mongoose-paginate-v2 plugin at Mongoose paginate npm page. At the end of this course you should be able to paginate your documents

Top comments (0)