Node.js – CRUD operations with MongoDB

By | 25/05/2022

In this post, we will see how to create a Web API with Node.js to run all CRUD operations for an entity called Person, using MongoDB as database.

We start creating a Node project called MongoCRUD using the command NPM INIT; it will create a package.json file like this:

[PACKAGE.JSON]

{
  "name": "mongocrud",
  "version": "1.0.0",
  "description": "Web API to run CRUD operations with MongoDB",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Damiano Abballe",
  "license": "ISC"
}



Then, we add a docker-compose file where we will define a MongoDb server and an instance of Mongo Express:

[DOCKER-COMPOSE.YAML]

version: '3'
services:
  # MongoDB container definition
  dockermongo:
    # name docker image 
    image: mongo
    # username and password Admin definition
    environment:
      - MONGO_INITDB_ROOT_USERNAME=admindb 
      - MONGO_INITDB_ROOT_PASSWORD=pass123 
    # volume definition
    volumes:
      - dbmongo:/data/dbPerson
    # network definition
    networks:
      - netMongoDBServer
    ports:
      - 27017:27017
  # mongo-express container definition 
  dockermongoexpress:
    # name docker image
    image: mongo-express
    # fixes MongoNetworkError when mongodb is not ready when mongo-express starts
    restart: always 
    # definition host and container port
    ports:
      - 8081:8081
    # definition of username and password MongoDB's Admin
    # name MongoDB container 
    environment:
      - ME_CONFIG_MONGODB_ADMINUSERNAME=admindb
      - ME_CONFIG_MONGODB_ADMINPASSWORD=pass123
      - ME_CONFIG_MONGODB_SERVER=dockermongo
    # network definition
    networks:
      - netMongoDBServer 
volumes:
  dbmongo:
    driver: local
networks:
    netMongoDBServer:
        driver: bridge



Finally, we install three libraries:
MongoDb

npm install mongodb

Express

npm install express

Cors

npm install cors



Now, we can develop the node application and we start defining the entity Person:

[PERSON.JS]

class Person
{
    constructor(name, surname, age)
    {
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
}
  
module.exports = { Person };



Then, we create two files: one called parameters.js where we will define the MongoDB parameters and the second one, called dbCore.js, where we will define the logic for CRUD operations:

[PARAMETERS.JS]

// connection string
const mongoDBConnection = "mongodb://admindb:pass123@localhost:27017";
// db name
const mongoDBName = "dbPerson";
// name of the collection
const collectionPeople = "people";

module.exports = { mongoDBConnection, mongoDBName, collectionPeople };



[DBCORE.JS]

const parameters = require('./parameters');
const { MongoClient } = require('mongodb');

// public method use to create a person
async function AddPerson(person)
{
    const mongoClient = new MongoClient(parameters.mongoDBConnection);
    return await Create(mongoClient, person);
}

// public method use to delete a person
async function DeletePerson(surName)
{
    const mongoClient = new MongoClient(parameters.mongoDBConnection);
    return await Delete(mongoClient, surName);
}

// public method use to update a person
async function UpdatePerson(person)
{
    const mongoClient = new MongoClient(parameters.mongoDBConnection);
    return await Update(mongoClient, person.surname, { name: person.name, age: person.age} );
}

// public method use to get a person by surname
async function PersonBySurname(surName)
{
    const mongoClient = new MongoClient(parameters.mongoDBConnection);
    return await GetOne(mongoClient, surName);
}

// public method use to get all people
async function People()
{
    const mongoClient = new MongoClient(parameters.mongoDBConnection);
    return await GetAll(mongoClient);
}

// private method use to open the database connection 
async function OpenConnection(mongoClient) {
    try {
        // Connect to the MongoDB 
        await mongoClient.connect();
    }
    catch (e) {
        console.error(e)
    };
}

// private method use to close the database connection
async function CloseConnection(mongoClient) {  
    try {
        // Close connect to the MongoDB
        await mongoClient.close();
    }
    catch (e) {
        console.error(e)
    };
}

// private method use to save a new person in MongoDB
async function Create(mongoClient, person)
{
    try {
        OpenConnection(mongoClient);
        return await mongoClient.db(parameters.mongoDBName).collection(parameters.collectionPeople).insertOne(person);
    } catch (error) {
        console.error(error);
    }
    finally{
        CloseConnection(mongoClient);
    }    
}

// private method use to delete a person in MongoDB
async function Delete(mongoClient, surnameInput)
{
    try {
        OpenConnection(mongoClient);
        return await mongoClient.db(parameters.mongoDBName).collection(parameters.collectionPeople).deleteOne({ surname: surnameInput });
    } catch (error) {
        console.error(error);
    }
    finally{
        CloseConnection(mongoClient);
    }    
}

// private method use to update a person in MongoDB
async function Update(mongoClient, surnameInput, updateFields)
{
    try {
        OpenConnection(mongoClient);
        return await mongoClient.db(parameters.mongoDBName).collection(parameters.collectionPeople).updateMany({ surname: surnameInput }, { $set: updateFields});
    } catch (error) {
        console.error(error);
    }
    finally{
        CloseConnection(mongoClient);
    }    
}

// private method use to get a person by surname in MongoDB
async function GetOne(mongoClient, surnameInput)
{
    try {
        OpenConnection(mongoClient);
        return await mongoClient.db(parameters.mongoDBName).collection(parameters.collectionPeople).findOne({ surname: surnameInput });
    } catch (error) {
        console.error(error);
    }
    finally{
        CloseConnection(mongoClient);
    }    
}

// private method use to get all people in MongoDB
async function GetAll(mongoClient)
{
    try {
        OpenConnection(mongoClient);
        return await mongoClient.db(parameters.mongoDBName).collection(parameters.collectionPeople).find({}).toArray();
    } catch (error) {
        console.error(error);
    }
    finally{
        CloseConnection(mongoClient);
    }    
}

// definition of pubblic methods
module.exports = { AddPerson, DeletePerson, UpdatePerson, PersonBySurname, People };



Now, we create a file called personController.js that it will be the Web API’s controller:

[PERSONCONTROLLER.JS]

const dbCore = require('../Core/dbCore');

// method used to get all people
const getPeople = async (req, res) => {
    const people = await dbCore.People()
    if (!people) return res.status(204).json({ 'message': 'No people found.' });
    res.json(people);
}

// method used to get a person by surname
const getPerson = async (req, res) => {
    const person = await dbCore.PersonBySurname(req.params.surname);
    if (!person) return res.status(204).json({ 'message': 'No person found.' });
    res.json(person);
}

// method used to delete a person
const deletePerson = async (req, res) => {
    const result = await dbCore.DeletePerson(req.params.surname);
    res.json(result);
}

// method used to create a new person
const createPerson = async (req, res) => {
    const result = await dbCore.AddPerson({
        name: req.body.name,
        surname: req.body.surname,
        age: req.body.age
    });
    res.json(result);
}

// method used to update a person
const updatePerson = async (req, res) => {
    const result = await dbCore.UpdatePerson({
        name: req.body.name,
        surname: req.body.surname,
        age: req.body.age
    });
    res.json(result);
}

// definition of pubblic methods
module.exports = { getPeople, getPerson, deletePerson, createPerson, updatePerson };



Finally, we create a file index.js where we will define the Web API:

[INDEX.JS]

// import express
var express = require('express');  
// import cors
const cors = require('cors')
// import body-parser used to parse json body into javascript object
const bodyParser = require("body-parser"); 
var app = express(); 
// definition of Rest API's port
var port = process.env.port || 1333;  
// definition of Person controller
const personController = require('./Controller/personController');

app.use(cors());
app.use(bodyParser.json());

// definition of routers
const router  = express.Router();   
router.get("/people", personController.getPeople);
router.get("/people/:surname", personController.getPerson);
router.delete("/people/:surname", personController.deletePerson);
router.post("/people/", personController.createPerson);
router.put("/people/", personController.updatePerson);

app.use("/api", router);

app.listen(port, (err) => {
    if (err) console.log(err);
    else console.log(`Server started on port: ${port}`);
  });



Now, we can run the application (obviously, we have to run the docker compose file before!) and then, using an API client, we can check all methods work fine:


CREATE PEOPLE


GET ALL PEOPLE


GET A PERSON


UPDATE A PERSON


DELETE A PERSON



CRUD OPERATIONS WITH MONGODB – CODE
https://github.com/ZoneOfDevelopment/MongoCRUD


Leave a Reply

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