CRUD Nodejs Express MongoDB Atlas Example | RESTful APIs Post/Get/Put/Delete & Mongoose Tutorial

Crud Nodejs Express Mongodb Tutorial

In the tutorial, I will introduce step by step how to create a ‘CRUD Nodejs, Express, MongoDB Atlas Example’ with a full-stack technologies: Express RestAPI Framework (Cors + Body-Parse) + Mongoose ODM + MongoDB Atlas database.

– First step, I draw a full stack diagram architecture for an overview of the project: “Nodejs CRUD RestAPIs with MongoDB” using Mongoose ODM.
– Next step, I design an integrative testsuite for CRUD Nodejs with MongoDB: post/get/put/delete requests and pagination with filtering and sorting request.
– Finally, I guide you with detail steps and running example code for build an Nodejs CRUD RestAPIs project with MongoDB Atlas.

Related posts:


Overview Architecture with Fullstack Diagram – CRUD Nodejs, Express, MongoDB Atlas Example

Below is the architecture of the tutorial ‘CRUD Nodejs, Express, MongoDB Atlas Example’:

Nodejs Express MongoDB CRUD RestApis
Nodejs Express MongoDB CRUD RestApis

To handling all POST/GET/PUT/DELETE RestAPI requests and do CRUD with MongoDB (Atlas) database, we create a backend web Node.js application with 4 main points:

  • To handle CRUD RestAPI requests with Node.js, we use Express.js framework.
  • To do CRUD operations with MongoDB database, we use Mongoose ODM queries.
  • We define all RestAPI urls in router.js.
  • We implement how to process each RestAPI requests in controller.js file.

Project Goal with Integrative Testsuite: CRUD Nodejs MongoDB Atlas Example

After the tutorial, we will understand overall diagram architecture and clearly picture how to create a full backend web restapis application with Node.js technology from abstract overview to specific helpful frameworks and details sourcecode for connecting all things in one application.

We will define 8 RestAPIs with POST/GET/PUT/DELETE methods for posting, fetching, updating, removing, pagination, filtering and sorting data from MongoDB database:

– For normally requests with POST/GET/PUT/DELETE methods, we create a first GROUP with 5 RestAPIs:

  1. POST RestAPI /api/customers/create will handle the submit data from client to save in MongoDB database
  2. GET RestAPI /api/customers/all will fetch all data from MongoDB database
  3. GET RestAPI /api/customers/onebyid/:id will get a single data by primary key id
  4. PUT RestAPI /api/customers/update/:id will update an existed record in MongoDB database
  5. DELETE RestAPI /api/customers/delete/:id will delete an existed record in MongoDB which is associated with a primary key id

– For advanced purpose such as Filtering, Pagination and Sorting, we create the second RestAPIs group:

  1. Filtering Request – GET RestAPI /api/customers/filteringbyage is used to fetch all records from MongoDB with a filtering by age
  2. Pagination Request – GET RestAPI /api/customers/pagination is used to fetch data from MongoDB with pagination purpose.
  3. Pagination Filtering and Sorting – GET RestAPI /api/customers/pagefiltersort is defined to fetch data from MongoDB with pagination, filtering by age and ordering by 2 fields firstname and lastname

Testcase 1 – Nodejs Express POST Request to MongoDB Atlas

Nodejs Express Post a data to MongoDB
Nodejs Express Post a data to MongoDB

Check MongoDB’s records:

Atlas MongoDB after Posting data
Atlas MongoDB after Posting data

Testcase 2 – Nodejs Express MongoDB GET Request: get all data from Mongodb

Nodejs get all data from MongoDB
Nodejs get all data from MongoDB

Testcase 3 – Nodejs Express MongoDB GET Request: retrieve one data record from MongoDB with a given id

Nodejs get a data with a specific id from MongoDB
Nodejs get a data with a specific id from MongoDB

Testcase 4 – Nodejs Express MongoDB UPDATE request

Nodejs Put request - update data to MongoDB
Nodejs Put request – update data to MongoDB

Testcase 5 – Nodejs Express MongoDB DELETE request: remove a record with a given id

Nodejs express delete request - remove data from MongoDB
Nodejs express delete request – remove data from MongoDB

Testcase 6 – Nodejs Express MongoDB Filtering request by a field

Nodejs Express Filtering Request - Filtering MongDB database with age=23
Nodejs Express Filtering Request – Filtering MongDB database with age=23

Testcase 7 – Nodejs Express MongoDB Pagination request

Nodejs Express Pagination request - with MongoDB
Nodejs Express Pagination request – with MongoDB

What does it mean? We had done a pagination request to fetch a second page page = 1 with a size of page is 7 (limit=7)

The RestAPI returns a json result with useful informantion as below:

  1. totalItems describes the number of records in database
  2. totalPages describes the total number of pages with requested limit
  3. limit describes the number of items for a fetching page
  4. currentPageNumber is the order number of requested page (currentPageNumber = page + 1)
  5. currentPageSize is the size of the current page (currentPageSize <= limit)
  6. customers is a dataset attached with the pagination request

Using MongoDB Compass query with OFFSET & LIMIT statement to check the above result:

MongoDB Skip and Limit query
MongoDB Skip and Limit query

Testcase 8 - Nodejs Express MongoDB Pagination Filtering and Sorting request

Nodejs Express Pagination Filtering and Sorting with MongoDB
Nodejs Express Pagination Filtering and Sorting with MongoDB

What does it mean? - The above request had done with 3 proccessing steps:

1. Do the Filtering with age=23, and We just have 3 Customer items in database having age is 23 so returned totalItems is 3. The totalPages is 2 because of 2 reason:
- limit: 2
- and totalPages = Math.ceil(data.count / limit) = Math.ceil(3 / 2)

2. Do the pagination with offset = 0 (limit*page)

3. Finally do the Sorting by firstname with ascending order and lastname with descending order:

Mongodb Pagination Filtering and Sorting
Mongodb Pagination Filtering and Sorting

How to Create Nodejs Express Mongoose CRUD MongoDB Project

Before creating a Nodejs project, we need to confirm that the Nodejs and npm had been installed in your computer development by cmd: node -v and npm -v

Checking Nodejs Environment Development
Checking Nodejs Environment Development

If these commandlines are not recognized by command prompt, it means you need to install them by visit the https://nodejs.org/en/ site and download installed package and do the nodejs setup for development later.

Now starting development! Create a folder and named it as Nodejs-Express-MongoDB-Example, go inside the folder, open a cmd and initiate a Nodejs project by cmd npm init. After all, a package.json file is created as below content:


{
  "name": "nodejs-express-mongodb-crud-example",
  "version": "1.0.0",
  "description": "Nodejs Express CRUD RestAPIs with Mongoose Example",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/loizenai"
  },
  "keywords": [
    "nodejs",
    "crud",
    "restapi",
    "mongoose",
    "example",
    "express"
  ],
  "author": "https://loizenai.com",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "mongoose": "^5.10.2",
    "sequelize": "^6.3.4"
  }
}

Here is the project structure of Nodejs MongoDB CRUD Example:

Nodejs MongoDB Crud project structure
Nodejs MongoDB Crud project structure

- mongodb.config.js is used to define MongoDB database's URL configuration
- customer.model.js is used to define a Mongoose model mapped with corresponding MongoDB database document schema.
- router.js is used to define all Nodejs Express RestAPI urls.
- controller.js is used to implement detail logic code to process each incoming request.
- server.js is used to implement a Nodejs Web server.

Install Nodejs Dependencies: Express, Cors, Body Parse, Mongoose

To development a 'Node.js MongoDB CRUD Example with Mongoose and Express RestAPIs', we need a set of packages to handle the full stack of the web backend proccessing, they includes Express framework, Cors, Body Parse, Mongoose packages.

  1. Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
    $ npm install express
    
  2. CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
    $ npm install cors
    
  3. Body-parser is the Node.js body parsing middleware. It is responsible for parsing incoming request bodies in a middleware before your handlers, available under the req.body property.
    $ npm install body-parser
    
  4. Mongoose is a promise-based Node.js ODM for MongoDB.
    $ npm install --save mongoose

We can install all the packages by one cmd:

$npm install --save express cors body-parser pg pg-hstore mongoose

Create Nodejs Mongoose Model Example

In the tutorial, 'Node.js Express MongoDB RestAPIs Example', We need define a Mongoose ODM model to represent a document in the customer collection, see details of coding in file customer.model.js:

const mongoose = require('mongoose');
 
const CustomerSchema = mongoose.Schema({
    firstname: String,
    lastname: String,
    address: String,
    age: { 
      type: Number, 
      min: 18, 
      max: 65, 
      required: true 
    },
    copyrightby: {
      type: String,
      default: 'https://loizenai.com'
    }
});

module.exports = mongoose.model('Customer', CustomerSchema);

See the mapping document in MongoDB:

Customer Document in MongoDB
Customer Document in MongoDB

Mongoose CRUD Queries with MongoDB

In the tutorial, we do some CRUD operations from Node.js application with MongoDB database by using Mongoose ODM, so from now we need cleary understand some CRUD Mongoose methods which we will use later:

  1. Document.prototype.save() - Saves this document by inserting a new document into the database if document.isNew is true, or sends an updateOne operation only with the modifications to the database, it does not replace the whole document in the latter case.

    Example Code:

    customer.save().then(data => {
    		// send uploading message to client
    		res.status(200).json({
    		  ...
    		});
    	}).catch(err => {
    		res.status(500).json({
    		  ...
    		});
    	});
  2. Model.find() - Finds documents with some filters or not

    Example Code:

    
    // find all documents
    await Customer.find({});
    
    // find all documents named john and at least 18
    await Customer.find({ firstnam: 'Smith', age: { $gte: 18 } }).exec();
    
    // executes, passing results to callback
    Customer.find({ firstname: 'Jack', age: { $gte: 18 }}, function (err, docs) {});
    
    // executes, name LIKE smith and only selecting the "firstname" and "age" fields
    await Customer.find({ firstname: /john/i }, 'firstname age').exec();
    
    // passing options
    await Customer.find({ firstname: /john/i }, null, { skip: 10 }).exec();
  3. Model.findById() - Finds a single document by its _id field. findById(id) is almost* equivalent to findOne({ _id: id }). If you want to query by a document's _id, use findById() instead of findOne()

    Example Code:

    // Find the Customer with the given `id`, or `null` if not found
    await Customer.findById(id).exec();
    
    // using callback
    Customer.findById(id, function (err, adventure) {});
    
    // select only the Customer firstname and age
    await Customer.findById(id, 'firstname age').exec();
  4. Model.findByIdAndUpdate() - Finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes if callback is passed.

    Example Code:

    Customer.findByIdAndUpdate(id, update, options, callback) // executes
    Customer.findByIdAndUpdate(id, update, options)  // returns Query
    Customer.findByIdAndUpdate(id, update, callback) // executes
    Customer.findByIdAndUpdate(id, update)           // returns Query
    Customer.findByIdAndUpdate()                     // returns Query
  5. Model.findByIdAndRemove() - Finds a matching document, removes it, passing the found document (if any) to the callback.

    Example Code:

    Customer.findByIdAndRemove(id, options, callback) // executes
    Customer.findByIdAndRemove(id, options)  // return Query
    Customer.findByIdAndRemove(id, callback) // executes
    Customer.findByIdAndRemove(id) // returns Query
    Customer.findByIdAndRemove()           // returns Query

Create Node.js Express RestAPI Example

For building the Nodejs Express RestAPIs Example project with MongoDB, we do 4 step for development:

  1. Create Express WEB Application Server
  2. Define All RestAPI URLs in router.js
  3. Configure MongoDB Database with Mongoose ODM
  4. Implement All RESTAPIs in controllers.js file

Create Express Application Server with MongoDB Connection

To implement an Express RestAPIs Application, firstly we need create a server with express app:

- server.js:

const express = require('express');
const app = express();
...
const server = app.listen(8080, function () {
 
  let host = server.address().address
  let port = server.address().port
 
  console.log("App listening at http://%s:%s", host, port); 
})

- For parsing body of requests, we need use body-parser dependency, add more code on server.js file:


...
var bodyParser = require('body-parser');
...
app.use(bodyParser.json());
...
const server = app.listen(8080, function () {
...
>

- To connect with MongoDB, we use below segment code:

mongoose.connect(dbConfig.url, { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => {
        console.log("Successfully connected to MongoDB.");    
    }).catch(err => {
        console.log('Could not connect to MongoDB.');
        process.exit();
    });

Here is all coding in the server.js file:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json())

// Configuring the database
const dbConfig = require('./app/config/mongodb.config.js');
const mongoose = require('mongoose');
 
mongoose.Promise = global.Promise;
 
// Connecting to the database
mongoose.connect(dbConfig.url, { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => {
        console.log("Successfully connected to MongoDB.");    
    }).catch(err => {
        console.log('Could not connect to MongoDB.');
        process.exit();
    });

require('./app/routes/customer.router.js')(app);
// Create a Server
var server = app.listen(8080, function () { 
  var host = server.address().address
  var port = server.address().port
 
  console.log("App listening at http://%s:%s", host, port) 
})

Define All Nodejs Express RestAPIs URLs in router.js

For making a routing with Express framework, we define all URLs in customer.router.js file:


module.exports = function(app) {
 
  var customers = require('../controllers/customer.controller.js');

  // Create a new Customer
  app.post('/api/customer/create', customers.create);

  // Retrieve all Customer
  app.get('/api/customer/retrieveinfos', customers.findall);

  // Retrieve a single Customer by Id
  app.get('/api/customer/findone/:id', customers.findone);

  // Update a Customer with Id
  app.put('/api/customer/updatebyid/:id', customers.update);

  // Delete a Customer with Id
  app.delete('/api/customer/deletebyid/:id', customers.delete);

  app.get('/api/customer/filteringbyage', customers.filteringByAge);

  app.get('/api/customer/pagination', customers.pagination);

  app.get('/api/customer/pagefiltersort', customers.paginationfilterandsort);
}

Configure MongoDB Atlas Database with URL

We create a file mongodb.config.js as below:

module.exports = {
  url: 'mongodb+srv://loizenai:loizenai@cluster0.esvi3.mongodb.net/loizenaidb'
}

Implement All RESTAPIs in controllers.js file

Nodejs Controller RestAPIs
Nodejs Controller RestAPIs

For handling Nodejs MongoDB CRUD RestAPIs' processing that been defined in router.js file, we implement all 8 working functions in controller.js file:

  1. create = (req, res) function is used to handle a POST request at the endpoint /api/customer/create, save a document to MongoDB database and return back a JSON message
  2. findall = (req, res) function is used to handle a GET request at the endpoint /api/customer/all to fetch all documents from MongDB and return back to client in JSON format
  3. findone = (req, res) function is used to handle a GET request at the endpoint /api/customer/findone/:id to get a specific document from MongoDB database with a given id and return back to client a JSON message
  4. filteringByAge = (req, res) function is used to handle a GET request at the endpoint /api/customer/filteringbyage to filter all documents in MongoDB by a given age value and return back all results to client in a Json message format
  5. pagination = async (req, res) function is used to handle a GET request at the endpoint /api/customer/pagination with 2 query parameters limit and page to get a batch of document from MongoDB database like as a pagination query
  6. pagingfilteringsorting = async (req, res) function is used to handle a GET request at the endpoint /api/customers/pagefiltersort to do an association quering operation: pagination, plus filtering by age and sorting by firstname and lastname from MongoDB database with 3 request query parameters limit, page, age
  7. update = async (req, res) function is used to handle a PUT request at the endpoint /api/customer/update/:id to update a specific document from MongoDB database with a given id
  8. delete = (req, res) function is used to handle a DELETE request at the endpoint /api/customer/deletebyid/:id to delete a specific document from MongoDB database with a given id from the path parameter

Implement Node.js Express CRUD RestAPIs: Post/Get/Put/Delete requests

Nodejs Express POST request

create = (req, res) function is used to handle a POST request at the endpoint /api/customer/create, save data to MongoDB database and return back a JSON message.

What will we do?

  • Create a Customer object from a request's body data
  • Use the Mongoose Model to save created object to MongoDB database
  • Return back a JSON message to client side

Remember to use the catch statement for handling any error if having unexpected exception.

exports.create = (req, res) => {

    const customer = new Customer({
                          firstname: req.body.firstname,
                          lastname: req.body.lastname,
                          age: req.body.age,
                          address: req.body.address,
                        });
 
    // Save a Customer in the MongoDB
    customer.save().then(data => {
                    // send uploading message to client
                    res.status(200).json({
                      message: "Upload Successfully a Customer to MongoDB with id = " + data.id,
                      customer: data,
                    });
                }).catch(err => {
                    res.status(500).json({
                      message: "Fail!",
                      error: err.message
                    });
                });
};

Nodejs Express GET request

Now we implement fullstack from Nodejs Express GET request using Mongoose ODM to retrieve data from MongoDB database. We create 2 GET request methods:

  • findall = (req, res) function is used to handle a GET request at the endpoint /api/customer/retrieveinfos to fetch all documents from MongoDB and return back to client in JSON format
  • findone = (req, res) function is used to handle a GET request at the endpoint /api/customer/findone/:id to get a specific document from MongoDB database with a given id and return back to client a JSON message

1. How to implement findall = (req, res) function? It's so simple

  • Using Customer.find() function to fetch all documents from MongoDB database
  • Return a JSON message to client with needed information
  • Do not forget to handle any unexpected error by using catch statement if having any exception throwed

exports.findall = (req, res) => {
    Customer.find().select('-__v').then(customerInfos => {
          res.status(200).json({
            message: "Get all Customers' Infos Successfully!",
            numberOfCustomers: customerInfos.length,
            customers: customerInfos
          });
        }).catch(error => {
          // log on console
          console.log(error);

          res.status(500).json({
              message: "Error!",
              error: error
          });
        });
};

2. How to implement findone = (req, res) function? It's so simple

  • Using Customer.findById(req.params.id) function to fetch a specific document from MongoDB database with a given customerId
  • Return a JSON message to client with needed information
  • Do not forget to handle any unexpected error by using catch statement if having any exception throwed

- Coding here:

// find a Customer by id
exports.findone = (req, res) => {
    Customer.findById(req.params.id).select('-__v')
        .then(customer => {
          res.status(200).json({
            message: " Successfully Get a Customer from MongoDB with id = " + req.params.id,
            customer: customer
          });
        }).catch(err => {
            if(err.kind === 'ObjectId') {
                return res.status(404).send({
                    message: "Customer not found with id " + req.params.id,
                    error: err
                });                
            }
            return res.status(500).send({
                message: "Error retrieving Customer with id " + req.params.id,
                error: err
            });
        });
};

Nodejs Express PUT request

Now we implement a fullstack solution: Nodejs Express RestAPI PUT request to get data from MongoDB using Mongoose ODM.

update = (req, res) function is used to handle a PUT request at the endpoint /api/customer/updatebyid/:id to update a specific document from MongoDB database with a given id

How to implement it? Just simple:

  • Use Mongoose ODM Model's function: findByIdAndUpdate() to fetch a specific Customer with a given id from request parameter:
    Customer.findByIdAndUpdate(req.params.id, ...)
  • If existing a specific instance with the given id, it will update new values from body request to the founded Customer object and save the object again to MongoDB database, then returns back to client a Json message with 200 status code:
    res.status(200).json({
                  message: "Update successfully a Customer with id = " + req.params.id,
                  customer: customer,
                });
  • If not found a document with a given id, it will return back to client a Json message with 404 status code:
    if(!customer) {
                    return res.status(404).send({
                        message: "Error -> Can NOT update a customer with id = " + req.params.id,
                        error: "Not Found!"
                    });
                }
  • Don't forget to use a catch statement to handle any unexpected-exception

- Coding:

exports.update = (req, res) => {
    // Find customer and update it
    Customer.findByIdAndUpdate(
                    req.params.id, 
                      {
                        firstname: req.body.firstname,
                        lastname: req.body.lastname,
                        age: req.body.age
                      }, 
                        {new: true}
                    ).select('-__v')
        .then(customer => {
            if(!customer) {
                return res.status(404).send({
                    message: "Error -> Can NOT update a customer with id = " + req.params.id,
                    error: "Not Found!"
                });
            }

            res.status(200).json({
              message: "Update successfully a Customer with id = " + req.params.id,
              customer: customer,
            });
        }).catch(err => {
            return res.status(500).send({
              message: "Error -> Can not update a customer with id = " + req.params.id,
              error: err.message
            });
        });
};

Nodejs Express DELETE request

exports.delete = (req, res) function is used to handle a DELETE request at the endpoint /api/customer/deletebyid/:id to delete a specific document from MongoDB database with a given id from the path parameter.

How to implement it?

  • Using the Mongoose Model's function: findByIdAndRemove to check the existence of a specific document in MongoDB database with a given id: Customer.findByIdAndRemove(customerId)
  • If it does NOT existed, return a 404 NOT-FOUND message
  • Otherwise, the Mongoose model's function: findByIdAndRemove will delete the document in MongoDB database then returns back a successfully message with 200 status code to client side
  • Do not forget to handle any unexpected error by using a catch statement

- Coding :


exports.delete = (req, res) => {
    let customerId = req.params.id

    Customer.findByIdAndRemove(customerId).select('-__v -_id')
        .then(customer => {
            if(!customer) {
              res.status(404).json({
                message: "Does Not exist a Customer with id = " + customerId,
                error: "404",
              });
            }
            res.status(200).json({
              message: "Delete Successfully a Customer with id = " + customerId,
              customer: customer,
            });
        }).catch(err => {
            return res.status(500).send({
              message: "Error -> Can NOT delete a customer with id = " + customerId,
              error: err.message
            });
        });
};

Advance 1: Nodejs Mongoose Filtering MongoDB Atlas

Now we create an filtering restapi to get data from MongoDB database with some condition by Nodejs Express and MongoDB Queries:

filteringByAge = (req, res) function is used to handle a GET request at the endpoint /api/customer/filteringbyage to filter all document in MongoDB by a given age value and return back all results to client in a Json message format.

How to implement it? Just follow simple steps:

  • Get an age value from request query for using to do the filter later
  • Using the .find({}) method of Mongoose model to retrieve all document from MongoDB database with a filter by age condition: {age: age}
  • Build a Json message with informative selected fields and return it back to client side.
  • Do not forget to handle any exception when processing by using try-catch statement!

Coding:


exports.filteringByAge = (req, res) => {
  const age = parseInt(req.query.age);  

  Customer.find({age:age}).select("-__v")
    .then(results => {
      res.status(200).json({
        "message": "Get all Customers with age = " + age,
        "size": results.length,
        "customers": results
      });  
    }).catch(err => {
      console.log(err);
      res.status(500).json({
        message: "Error!",
        error: err
      });
    });
}

Advance 2: Nodejs Mongoose Pagination MongoDB Atlas

pagination = (req, res) function is used to handle a GET request at the endpoint /api/customer/pagination with 2 query parameters limit and page to get a batch of documents from MongoDB database for the pagination query.

To do the pagination with MongoDB database by Mongoose ODM, we use the .find({}) method with skip and limit.

Simple steps to implement the pagination request:

  • Get the page and limit parameters from the request query
  • Calulate an offset(skip) from page and limit parameters
    const offset = page ? page * limit : 0;
  • Do the pagination query to MongDB database using the find({}) method of Mongoose model as blow format:
    let results = await Customer.find({})  // You may want to add a query
                      .skip(offset) // Always apply 'skip' before 'limit'
                      .limit(limit)
                      .select("-__v"); // This is your 'page size'
  • Construct a JSON message with a set of informative fields and return back to client side
  • Remember to handle the un-expected error by using try-catch statement

Detail Coding:

exports.pagination = async (req, res) => {

  try {

    const page = parseInt(req.query.page);
    const limit = parseInt(req.query.limit); // Make sure to parse the limit to number
    
    const offset = page ? page * limit : 0;
  
    // We are using the '3 layer' architecture explored on the 'bulletproof node.js architecture'
    // Basically, it's just a class where we have our business logic
    
    let results = await Customer.find({})  // You may want to add a query
                      .skip(offset) // Always apply 'skip' before 'limit'
                      .limit(limit)
                      .select("-__v"); // This is your 'page size'
        
    let numOfCustomer = await Customer.countDocuments({});
  
    res.status(200).json({
      "message": "Paginating is completed! Query parameters: page = " + page + ", limit = " + limit,
      "totalPages": Math.ceil(numOfCustomer / limit),
      "totalItems": numOfCustomer,
      "limit": limit,
      "currentPageSize": results.length,
      "customers": results
    });      
  } catch (error) {
    res.status(500).send({
      message: "Error -> Can NOT complete a paging request!",
      error: error.message,
    });    
  }

}

Advance 3: Nodejs Mongoose Pagination Filtering Sorting with MongoDB

paginationfilterandsort = (req, res) function is used to handle a GET request at the endpoint /api/customer/pagefiltersort to do an association quering operation: pagination, plus filtering by age and sorting by firstname and lastname from MongoDB database with 3 request query parameters limit, page, age.

We continue to use the method .find({}) to do the associated operation: pagination plus filtering and sorting query. So we add more conditions with .find({}) method:

  • filtering condition: {age: age} - .find({age:age})
  • sorting clause – using to sort documents by 2 fields firstname with ascending direction and lastname with descending direction:
    .sort({"firstname": 1, "lastname": -1})

Straightforward steps to implement the Pagination + Filtering and Sorting function:

  • Retrieve 3 parameters from incoming request query: limit, page for pagination and age for filtering.
  • Calulate an offset for Mongoose pagining query later:
    const offset = page ? page * limit : 0;
  • Do the Mongoose pagination filtering and sorting with .find({}) method:
    let results = await Customer.find({age: age})  // You may want to add a query
                      .skip(offset) // Always apply 'skip' before 'limit'
                      .limit(limit)
                      .sort({"firstname": 1, "lastname": -1})
                      .select("-__v"); // This is your 'page size'
  • Construct a JSON message with informative fields and return back to client side:
    res.status(200).json({
      "message": "Paginating is completed! Query parameters: page = " + page + ", limit = " + limit,
      "totalPages": Math.ceil(numOfCustomer / limit),
      "totalItems": numOfCustomer,
      "limit": limit,
      "age-filtering": age,
      "currentPageSize": results.length,
      "customers": results
    });    
  • Do NOT forget to handle an un-expected errors with try-catch statement.
    try{
        //...
    }catch(error) {
        res.status(500).send({
          message: "Error -> Can NOT complete a paging request!",
          error: error.message,
        });
    }   

– Coding here:

exports.paginationfilterandsort = async (req, res) => {
  try {
    const page = parseInt(req.query.page);
    const limit = parseInt(req.query.limit); // Make sure to parse the limit to number
    const age = parseInt(req.query.age);
    
    const offset = page ? page * limit : 0;
    
    let results = await Customer.find({age: age})  // You may want to add a query
                      .skip(offset) // Always apply 'skip' before 'limit'
                      .limit(limit)
                      .sort({"firstname": 1, "lastname": -1})
                      .select("-__v"); // This is your 'page size'
        
    let numOfCustomer = await Customer.countDocuments({age: age});

    res.status(200).json({
      "message": "Paginating is completed! Query parameters: page = " + page + ", limit = " + limit,
      "totalPages": Math.ceil(numOfCustomer / limit),
      "totalItems": numOfCustomer,
      "limit": limit,
      "age-filtering": age,
      "currentPageSize": results.length,
      "customers": results
    });    
  } catch (error) {
    res.status(500).send({
      message: "Error -> Can NOT complete a paging + filtering + sorting request!",
      error: error.message,
    });
  }
};

Sourcecode

– Here is a full sourcecode for “CRUD Nodejs, Express, MongoDB Atlas Example”:

Nodejs-Express-MongoDB-CRUD-Example

– Github Sourcecode:

Nodejs Express MonngoDB CRUD Example

Further Reading

Related posts:


2 thoughts on “CRUD Nodejs Express MongoDB Atlas Example | RESTful APIs Post/Get/Put/Delete & Mongoose Tutorial”

  1. Pingback: John

Leave a Reply

Your email address will not be published. Required fields are marked *