loading...
Cover image for Designing RESTful API with NodeJs, Express & MongoDB

Designing RESTful API with NodeJs, Express & MongoDB

mayankjoshi profile image mayank joshi Updated on ・7 min read

In this lesson, we are going to design a REST API based application to create a movie database. All the operations such as Create, Update, Read, Delete (CURD) will be done using the REST calls.

Pre-requisite: I’m assuming that you have a decent knowledge of Node Js, MongoDB and Express(a NodeJs platform).

If you don’t know about HTTP protocols like the GET, POST, etc. I highly recommend checking out this post HTTP request method – REST API verbs to understand them better.

1. Confirm Node Installation

Before proceeding further, confirm that you have node and npm package already installed in your system using following commands

$ node -v                                                          
$ npm -v

2. Initialize a New App

Great, now let’s create an empty directory, and initialize a new app in it.

$ mkdir CURD_using_node
$ cd CURD_using_node
$ npm init 

After completing the setup, a file name as package.json will be generated in your current folder. The default main file name will be index.js, but here we have updated it to app.js

Now, we need to install the Express Js locally in our current project folder.

$ npm install express --save 

Creating a Database

I am assuming you have already installed MongoDB in your operating system. If not please install it. You can check if MongoDB is installed or not using the following command.

$ mongo

Is mongo installed? Yes. Perfect now let’s create a new database in mongo and name is “my_db”

$ db my_db

3. Creating the APP

Let’s start by creating a file called app.js (or index.js) and creating an express server. Copy the following code in the app.js file.

var express = require('express');
var app = express();
app.get("/", function(req, res){
    res.write("nlogn.in says hello");
});
app.port(3000);

If you will run this code using the following command and try to browse to http://localhost:3000, if everything goes right, you will see, nlogn.in says hello printed on your browser screen. If it didn’t work, then there might be some problem with your Node installation.

$ node app.js                 //it starts the server

Assuming that everything worked fine, update the content of the app.js file with the following code.

As you can see from the app.js file, we are including a file name movies.js. This movie.js is going to contain code to handle all of our REST calls.

So, now let’s create a new file named movies.js, and this going to contain our code to handle the REST calls. Create a file named movies.js and copy-paste the following code in it.


Does it seem overwhelming?😲

Wait let me break it down for you 🔨.

1. Connecting to the MongoDB

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/my_db', { useNewUrlParser: true , useFindAndModify: false, useUnifiedTopology: true });

var movieSchema = mongoose.Schema({
    movieId: Number,
    name: String,
    year: Number,
    rating: Number
});

var movies = mongoose.model("movies", movieSchema);
  1. The first statement is importing the mongoose module(used to connect to MongoDB in Express) in our application
  2. It makes the connection to the Mongo database. mongodb://localhost/my_db is the connection URL, where my_db is the name of your database where you will create collections.
  3. This defines a schema for the collection. It tells, what are the variables you are going to store and what are their datatypes.
  4. The last line creates a collection in my_db database with above-mentioned schema and returns the connection instance which is stored in variable movies

2. Designing the GET Method

router.get("/", function(req, res){
    movies.find({},{'_id':0, '__v':0}).exec(function(err, response){
        if(err) throw err;
        res.status(200);
        res.json(response);
    })
});

This method handles GET requests. Whenever will visit the URL http://localhost:3000/movies this will return all the movies and their related information in JSON format.

movies.find({},{‘_id’:0, ‘__v’:0}) This code is going to make a query to the database, and if there will be no error it will fetch all the records and store it in the response variable. Here ‘_id’:0, ‘__v’:0 means, we don’t want these parameters in the response.
Alt Text

router.get("/:type/:value", function(req, res){
    if(req.params.type!="name"&&req.params.type!="year"&&req.params.type!="movieId"){
        res.status(400);
        res.json({message: "Bad Request", value:req.params.type});
    }
    else{
        var type = req.params.type;
        var value = req.params.value;
        movies.find({[type]:value},{'_id':0,'__v':0},function(err, response){
            if(err)
                res.json({message: "Bad Request", value:req.params.type});
            else{
                res.status(200);
                res.json(response);
            }
        });
    }
});

This is similar to the above GET method except now we are passing the parameters in the URL, to allow filtering in the result. For example, you can get details of all the movies in that particular year.
The application supports filtering based on movie id, name, year and rating.

Let’s say you want to filter out all the movies with rating 8.3, for this you will make the following request:

CURL -X GET localhost:3000/movies/rating/8.3               results in all movies published in 1996
CURL -X GET localhost:3000/movies/year/1996             results in all movies published in 1996

Alt Text

3. Designing the POST Method

router.post("/", function(req, res){
    if(!req.body.name || !req.body.year || !req.body.rating){
        res.status(400);
        res.json({message: "Bad Request",Details: {movieId:id, Name:req.body.name, Year: req.body.year, rating: req.body.rating}});
    }
    else{
        var newMovie = new movies({
            movieId: id,
            name: req.body.name,
            year: req.body.year,
            rating: req.body.rating
          });
          newMovie.save(function(err, mov){
             if(err)
                res.json({message: "Database error", type: "error"});
             else{
                res.status(201);
                res.json({Status:"Success",Details: {movieId:id, Name:req.body.name, Year: req.body.year, rating: req.body.rating}});
            }
          });
          id=id+1;
    }
});

So, as the name suggests this method supports creating a new resource in the database. But how does it work?

So, when a user makes a well-formed POST request with parameters such as movie name, years and rating, we create a newMovie document from Movies model and save it to our DB using the newMovie.save() function, but if we receive any empty field or do not receive any field, we will send an error response (Note, the user is not sending a movie id in a parameter, we are generating it ourselves).

The response user going to receive for successful POST request will be in JSON format containing the movie id, name, year, rating with a success message.
Alt Text

4. Designing PUT Method

router.put("/", function(req, res){
    if(!req.body.movieId){
        res.status(400);
        res.json({message: "Bad Request",Details: {movieId:id, Name:req.body.name, Year: req.body.year, rating: req.body.rating}});
    }
    else{
        var movieId = req.body.movieId;
        var newMovie ={
            name: req.body.name||"N/A",
            year: req.body.year||0,
            rating: req.body.rating||0
        };

      movies.findOneAndUpdate({"movieId":movieId},{$set:newMovie},{returnNewDocument : true}).exec(function(err, mov){
             if(err)
                res.json({message: "Query error", type:err});
             else{
                res.status(201);
                res.json({Status:"Success",Details: mov});
            }
        });
    }
});

The PUT request is made to update an already existing document(record) in a database. There are many ways to update database records in ExpressJS, here we will be using the findOneAndUpdate method.

The findOneAndUpdate(condition, updates, callbacks) methods, accepts 3 arguments, a condition(here we are going to use movie id to find a document which needs to be updated), the update argument consists of document for movie model with parameters that need to be updated( here we are updating movie name, year, rating and if a parameter is not provided in an updated request we are marking it NULL/empty) and callback function returning an error in case the update is unsuccessful or response, containing the updated result in JSON format.
Alt Text

5. Designing the Delete Method

Till now we have covered Create, Read and Update, now we will design a method to delete a record form the MongoDB. For performing deletion of record we are going to use deleteOne() method.

router.delete("/:type/:value", function(req, res){
    if(req.params.type!="name"&&req.params.type!="year"&&req.params.type!="movieId"){
        res.status(400);
        res.json({message: "Bad Request", value:req.params.type});
    }
    else{
        var type = req.params.type;
        var value = req.params.value;
        movies.deleteOne({[type]:value},function(err, mov){
            if(err){
                 res.json({message: "Database error", type: "error"});
            }
            else{
                res.status(200);
                res.json({Status:"Success",Removed: {[type]:value}});
            }
        });
    }
});

The deleteOne(condition, callbacks) function is going to take two arguments, first one will be the delete condition i.e. a condition that should hold for the deletion to be successful. The deletion can be performed based on movie id, name, year, rating. In case many results are matching the delete condition only the first record will be deleted. If you want to alter this behaviour, you can use deleteMany(condition, callbacks).

On successful deletion, you will receive 200OK status and a JSON response containing the entry which is deleted.

Alt Text

Congratulations you successfully designed a REST API based application in NodeJs and Express. 🎉 🎉 🎉

We hope you enjoyed the post. The code for this post can be found at GitHub. Don't forget to give it a Star ⭐⭐⭐⭐

GitHub logo dermayank / CURD-app-with-node-js

Implementation of CURD(Create, Update, Read, Delete) using Express JS and MongoDb

If you found anything incorrect or want to add something, please comment.


This post was originally published at nlogn.in

Posted on Apr 15 by:

mayankjoshi profile

mayank joshi

@mayankjoshi

I love system design and most of the time I find myself learning or designing one of them. I'm highly active on twitter, So ping me there.

Discussion

markdown guide