A simple guide to starting with NodeJs, Express and MongoDB Part-2

vishal rana
9 min readMar 24, 2019

Congratulations, you have made to this blog it means you have gone through my first blog that explains the basic concept of Nodejs and how to build simple rest API with that. if not, I request you to go through the first blog, so that you’ll get the idea of what is going around here.

ok, let resume from where we left last time. In this story, we are going to get through the other API types that we mainly use. Till now we have created an API using the post method.

There is a list of HTTP methods that we mainly used to create API's, each API is used for different operations.

POST
GET
PUT
PATCH
DELETE

Always use POST method when there is new entry need to be registered in the database.POST is a non-idempotent and other methods like- get, put, delete, patch are idempotent means calling it multiple time doesn’t affect the state. On the other hand, calling multiple post request leads to a different state as it creates a new entry every time you hit the post method.

GET methods is mainly used to perform a read option. Get don’t have a body like POST. The data is sent in params only i.e in the URL.

PUT and PATCH are used to perform modifications and both are used in different scenarios. The PUT methods used to completely replace the document and on the other hand, PATCH is used to modify some attributes in the document.

DELETE is used to remove a particular document from the collection.

In the last blog, we used the POST method to register a new user and in return, we were simply returning the success message and code. we haven’t taken user password while registration.

Now, let's add another field in model.js with the name password that will hold our password. Now we don’t simply store the password in the database a simple string value, we need to store the password after encrypting the password.and for encrypting the password we are going to use a new module called bcryptjs, you can learn more by clicking here. Bcrypt will basically encrypt your password into a unique hash and the bcrypt is a one-way function means you can not decrypt the hash into the original string password.

Model.js

const mongoose = require('mongoose');
const schema = mongoose.Schema;
const userSchema = new schema({
firstName: { type: String, required: true },
lastName: { type: String },
email: { type: String, required: true, unique: true },
age: { type: Number },
gender: { type: String, enum: ['Male', 'Female'] },
createdAt: { type: Date, default: Date.now },
password:String
});
module.exports = mongoose.model('user', userSchema);

Let's implement bcryptjs first then we will create a login API.

let’s just start by installing bcryptjs using npm.

npm i --save bcryptjs

let make some modification in the previously created createUser api.

Your new user_action.js will look like this.

const model = require('./model');
const bcrypt = require("bcryptjs");
module.exports = {
createUser: async function (req, res) {
req.body.password = await bcrypt.hash(req.body.password, 10);
var Model = new model(req.body);
Model.save((err, data) => {
if (err) return res.json({ code: 400, message: "Error in creating new user" })
else
return res.json({ code: 201, message: "User created successfully." })
})
}
}

If you have noticed that we have used async and await keywords, what are they and why we have used it. Async/await is used to handle things synchronously. Since Nodejs is an asynchronous language so it doesn’t wait for the processes to complete, it basically passes them(the process keep in running in the background) and performs next operations. Now let’s try to create a user and see what we have but first let's drop the database and get a fresh one. You can use following commands to drop a database

//enter into mongo shell using mongo
$ mongo
$ show dbs
$ use demoDb
$ db.users.dropDatabase()

let’s check if the database empty or not.

show dbs
// this will list all the database.

Call the API createUser from the rest client.

I have added the password field in the request body and in the response, we are getting :

let check the data in the database using mongo shell.

use demoDb
db.users.findOne()

The above command will give the document that we have just created.

As you can see we our document has been created successfully and the password field is encrypted as well. Like I said before bcryptjs, encode the password and there is no way we can decode that, so how we are going to match the password? Now comes the functions that bcryptjs provide us. we can’t decode the password but we can compare the simple password with the decoded one if they match then we log in the user otherwise invalid credentials error.

Let's create a login API that will match the credentials of the user and grant him access to our application. we are going to use the POST method to create a login API as we’ll accept email and password in the request body.

user_action.jsconst model = require('./model');const bcrypt = require("bcryptjs");module.exports = {createUser: async function (req, res) {req.body.password = await bcrypt.hash(req.body.password, 10);var Model = new model(req.body);Model.save((err, data) => {if (err) return res.json({ code: 400, message: "Error in creating new           user" })elsereturn res.json({ code: 201, message: "User created successfully." })})},loginUser: async function (req, res) {let userDetails = await model.findOne({ email: req.body.email }).exec();let isPasswordMatch = await bcrypt.compare(req.body.password, userDetails.password);if (isPasswordMatch) {return res.json({ code: 200, message: "Success.", result: userDetails._id})} else {return res.json({ code: 404, message: "Invalid credentials." })}}}

index.js

const express    = require('express');const app    = express();const mongoose   = require('mongoose');const config   = require('./config');const bodyParser  = require('body-parser');const userAction   = require('./user_action');app.set('port',process.env.PORT || 8090);mongoose.connect(config.path);app.use(bodyParser.urlencoded({extended:false}));app.use(bodyParser.json());app.post('/createUser',(req,res)=>userAction.createUser(req,res));app.post('/login',(req,res)=>userAction.loginUser(req,res));app.listen(app.get('port'),()=>{console.log(`Server listening on ${app.get('port')}`);})

Let’s try hitting the login API.

Result:

Now generally we don’t just give all the user details after login, we generate token and return token in login API response, not the actual response. What is a token? A token is generally encrypted of your information that will be used to authorize what actions you are allowed to perform.we are going to see token based authorization in some another blog later , for now we are just returning the user id that we’ll use to fetch user details and update his response.let’s just finish up the other pending API.

GET method we are going to use for fetching user details. We are going to use the _id that we got in the login response as a result parameter.

The above result is our _id. An _id is a unique id for every document that is been generated by MongoDB.

Your files will look like this.

Index.js

const express    = require('express');const app    = express();const mongoose   = require('mongoose');const config   = require('./config');const bodyParser  = require('body-parser');const userAction   = require('./user_action');app.set('port',process.env.PORT || 8090);mongoose.connect(config.path);app.use(bodyParser.urlencoded({extended:false}));app.use(bodyParser.json());app.post('/createUser',(req,res)=>userAction.createUser(req,res));app.post('/login',(req,res)=>userAction.loginUser(req,res));app.get('/userDetails/:id',(req,res)=>userAction.fetchUserDetails(req,res));app.listen(app.get('port'),()=>{console.log(`Server listening on ${app.get('port')}`);})

As you can see we are accepting id in the URL.

user_action.js

const bcrypt = require("bcryptjs");module.exports = {createUser: async function (req, res) {req.body.password = await bcrypt.hash(req.body.password, 10);var Model = new model(req.body);Model.save((err, data) => {if (err) return res.json({ code: 400, message: "Error in creating new           user" })elsereturn res.json({ code: 201, message: "User created successfully." })})},loginUser: async function (req, res) {let userDetails = await model.findOne({ email: req.body.email }).exec();let isPasswordMatch = await bcrypt.compare(req.body.password, userDetails.password);if (isPasswordMatch) {return res.json({ code: 200, message: "Success.", result: userDetails._id })} else {return res.json({ code: 404, message: "Invalid credentials." })}},fetchUserDetails: function (req, res) {model.findById(req.params.id, (err, data) => {if (err) return res.json({ code: 400, message: "Error in fetchig user details." })else {let { firstName, lastName, email, age, gender } = data;let response = { firstName, lastName, email, age, gender }return res.json({ code: 200, message: "Success.", userDetails: response })}})}}

Response:

PATCH: Let’s create an API that will update the user details.

Your index.js will look like this.

const express    = require('express');const app    = express();const mongoose   = require('mongoose');const config   = require('./config');const bodyParser  = require('body-parser');const userAction   = require('./user_action');app.set('port',process.env.PORT || 8090);mongoose.connect(config.path);app.use(bodyParser.urlencoded({extended:false}));app.use(bodyParser.json());app.post('/createUser',(req,res)=>userAction.createUser(req,res));app.post('/login',(req,res)=>userAction.loginUser(req,res));app.get('/userDetails/:id',(req,res)=>userAction.fetchUserDetails(req,res));app.patch('/updateUser/:id',(req,res)=>userAction.updateUser(req,res));app.listen(app.get('port'),()=>{console.log(`Server listening on ${app.get('port')}`);})

user_action.js

const model = require('./model');const bcrypt = require("bcryptjs");module.exports = {createUser: async function (req, res) {req.body.password = await bcrypt.hash(req.body.password, 10);var Model = new model(req.body);Model.save((err, data) => {if (err) return res.json({ code: 400, message: "Error in creating new           user" })elsereturn res.json({ code: 201, message: "User created successfully." })})},loginUser: async function (req, res) {let userDetails = await model.findOne({ email: req.body.email }).exec();let isPasswordMatch = await bcrypt.compare(req.body.password, userDetails.password);if (isPasswordMatch) {return res.json({ code: 200, message: "Success.", result: userDetails._id })} else {return res.json({ code: 404, message: "Invalid credentials." })}},fetchUserDetails: function (req, res) {model.findById(req.params.id, (err, data) => {if (err) return res.json({ code: 400, message: "Error in fetchig user details." })else {let { firstName, lastName, email, age, gender } = data;let response = { firstName, lastName, email, age, gender }return res.json({ code: 200, message: "Success.", userDetails: response })}})},updateUser:function(req,res){model.findByIdAndUpdate(req.params.id,{$set:req.body},(err,data)=>{if (err) return res.json({ code: 400, message: "Error in fetchig user details." })else{return res.json({code:201,message:"User details updated successfully."})}})}}

Result:

We are passing the id of the user whose data we are trying to update and the values we are passing in the body. In this API, I’m updating the age of the user.

Let’s check the database if the document been updated or not.

As you can see before the age was 22 and after the age is updated to 23.

Let’s make our last API that is delete.

DELETE: is used to remove the document from the database.We will delete the user using the same _id.

index.js

const express    = require('express');const app    = express();const mongoose   = require('mongoose');const config   = require('./config');const bodyParser  = require('body-parser');const userAction   = require('./user_action');app.set('port',process.env.PORT || 8090);mongoose.connect(config.path);app.use(bodyParser.urlencoded({extended:false}));app.use(bodyParser.json());app.post('/createUser',(req,res)=>userAction.createUser(req,res));app.post('/login',(req,res)=>userAction.loginUser(req,res));app.get('/userDetails/:id',(req,res)=>userAction.fetchUserDetails(req,res));app.patch('/updateUser/:id',(req,res)=>userAction.updateUser(req,res));app.delete('/user/:id',(req,res)=>userAction.deleteUser(req,res))app.listen(app.get('port'),()=>{console.log(`Server listening on ${app.get('port')}`);})

user_action.js

const model = require('./model');const bcrypt = require("bcryptjs");module.exports = {createUser: async function (req, res) {req.body.password = await bcrypt.hash(req.body.password, 10);var Model = new model(req.body);Model.save((err, data) => {if (err) return res.json({ code: 400, message: "Error in creating new           user" })elsereturn res.json({ code: 201, message: "User created successfully." })})},loginUser: async function (req, res) {let userDetails = await model.findOne({ email: req.body.email }).exec();let isPasswordMatch = await bcrypt.compare(req.body.password, userDetails.password);if (isPasswordMatch) {return res.json({ code: 200, message: "Success.", result: userDetails._id })} else {return res.json({ code: 404, message: "Invalid credentials." })}},fetchUserDetails: function (req, res) {model.findById(req.params.id, (err, data) => {if (err) return res.json({ code: 400, message: "Error in fetchig user details." })else {let { firstName, lastName, email, age, gender } = data;let response = { firstName, lastName, email, age, gender }return res.json({ code: 200, message: "Success.", userDetails: response })}})},updateUser: function (req, res) {model.findByIdAndUpdate(req.params.id, { $set: req.body }, (err, data) => {if (err) return res.json({ code: 400, message: "Error in fetchig user details." })else {return res.json({ code: 201, message: "User details updated successfully." })}})},deleteUser: function (req, res) {model.findByIdAndDelete(req.params.id,(err,data)=>{if (err) return res.json({ code: 400, message: "Error in deleting user." })else {return res.json({ code: 201, message: "User deleted successfully." })}})}}

Response:

Let’s check the database if the document still there or not.

As you can see there is no entry in the database.

Congratulations you have just finished the basic crud operation using Nodejs, express, and MongoDB in the simplest form possible.

Feel free to ask any questions and let me know your feedback.

--

--