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