DEV Community

loading...
Cover image for Build a REST API with Node, Express and MongoDB

Build a REST API with Node, Express and MongoDB

shubham1710 profile image Kumar Shubham Originally published at Medium Updated on ・10 min read

APIs are a very common thing nowadays. They are used literally everywhere on the website. APIs serve as the connection between the database which stores all the data and the frontend with which the user interacts with to get access to the data.

API mean Application Programming Interface which is a set of clearly defined methods of communication between the frontend and the database.

REST which stands for Representational State Transfer is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.

REST APIs mostly use JSON as the preferred choice for transferring data as they are easy to understand and is readable.

In this tutorial, we will be using Node, Express and MongoDB to create a REST API which would support the four operations — GET, POST, PUT and DELETE.

So, let’s first discuss these four operations and try to understand what they actually mean in the context of API development.

  1. GET — GET means to read the data. The function of this operation is to retrieve the data from the database and present it to the user.
  2. POST — POST, as the name suggests, is used to post/add new data to the database. It allows users to add new data to the database.
  3. PUT — PUT means to update the data already present in the database.
  4. DELETE — It is used to delete any existing data from the database.

So, our REST API will perform all these four operations. We will use the Express package to make our work easier. We will use MongoDB as the NoSQL database to store all our data. MongoDB stores data in JSON format.

So, we will do it step by step. First, we would build the API endpoints and then we would connect to the database to perform actual operations. We would use Postman software for API testing.

Setting up the Project

First of all, we need to download Node on our system. Then we can start creating our project.

So, first of all, we need to create a folder in our system where we would love to build our project. I kept the name of the folder as rest-api.

Then we need to move into the rest-api folder we created just now. Now to start a new project, we would run the following command within the folder:-

npm init
Enter fullscreen mode Exit fullscreen mode

It will ask us various questions regarding the project like name, description and other things. We would like to keep everything in the default mode except the name and description which we can add as per our convenience.

After completion, we will see a package.json file in the folder. It contains all the data we just gave to create this file. You can see the entry point is index.js file.

After creating the package.json file, we need to download Express on our machine. To install Express, we can:-

npm install express --save
Enter fullscreen mode Exit fullscreen mode

This will download and save express in our system and also will add express as a dependency in our package.json file.

We will also like to download a development dependency named nodemon which will allow us to develop faster. It will help us to avoid restarting the server each time we make a change and will automatically refresh which would save us a lot of time.

So, to install nodemon we would do:

npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Notice that we have used save-dev to install and add it in package.json file as a dev dependency as we using it speed up our development process.

Now, we need to download MongoDB in our system and then create the cluster and connect it with your local computer.

Next, we need to download mongoose to interact with the MongoDB database from our express application.

To install mongoose, do the following:

npm install mongoose --save
Enter fullscreen mode Exit fullscreen mode

Now, we are ready to start building our REST API. Before starting, I would like to show my package.json file so that you can verify everything is going perfect.

{
  "name": "rest-api",
  "version": "1.0.0",
  "description": "Test Rest API",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Shubham",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "mongoose": "^5.11.9"
  },
  "devDependencies": {
    "nodemon": "^2.0.6"
  }
}
Enter fullscreen mode Exit fullscreen mode

So, let’s start building our REST API. First of all, we need to create a file named index.js as we can see it is the entry point to our application.

The index file

We would start with the index.js file. We would start with requiring express into our system.

const express = require('express');
Enter fullscreen mode Exit fullscreen mode

We will then set up our express app by writing the following line of code:-

const app = express();
Enter fullscreen mode Exit fullscreen mode

So, then we would set up a GET function to test it out using the browser. We pass a message as the response when we have a GET request to localhost:4000/api.

app.get('/api', (req, res) => res.send('Its working!'));
Enter fullscreen mode Exit fullscreen mode

We will then set up our application to start listening to the requests. We will use 4000 as the port number. We have used the OR operator there so that if there is any port number defined via environment variables, it could use that otherwise it will use 4000. You can choose the port number as per your choice. We will console.log a message to check if it is working properly.

app.listen(process.env.port || 4000, function(){
   console.log('now listening for requests');
});
Enter fullscreen mode Exit fullscreen mode

So, when we would start the server now using:

nodemon index
Enter fullscreen mode Exit fullscreen mode

When we go to localhost:4000/api we would see the message as ‘It’s working!’. Also, in console, we would get the message we set for the console.

So, here we are, with the express server set up properly and we sent our first GET request successfully.

Now, we would like to have all our four operations in a separate file called api.js under routes folder as we do not want to push everything into index.js file.

So, we would remove the app.get part in this index.js file. We would like to add the mongoose as a requirement in our file.

const mongoose = require('mongoose');
Enter fullscreen mode Exit fullscreen mode

Next, below the set up of our express app, we would like to connect to MongoDB. We would do so with the following code:

mongoose.connect('mongodb://localhost/ourdata');
mongoose.Promise = global.Promise;
Enter fullscreen mode Exit fullscreen mode

Here, ourdata is the name of the model we will be creating in MongoDb later on in this tutorial.

We also update the promises of the mongoose as the global promise since mongoose.promise is depreciated now.

Next, we would add a few more middlewares in the file. We would first add support to serve static files. Though we won't be serving static files in this tutorial but having it is nice since we would need to add a frontend anyway later on to use the APIs.

app.use(express.static('public'));
Enter fullscreen mode Exit fullscreen mode

We would then add Express parser to parse the data sent or received from the database.

app.use(express.json());
Enter fullscreen mode Exit fullscreen mode

We then set up the app to use the new api.js file we would create to hold our all four operations.

app.use('/api',require('./routes/api'));
Enter fullscreen mode Exit fullscreen mode

We have added ‘/api’ in the starting to avoid adding it to all four of the operations.

Finally, we add a middleware to handle the errors that occurred during the operations.

app.use(function(err,req,res,next){
   res.status(422).send({error: err.message});
});
Enter fullscreen mode Exit fullscreen mode

Here is the finalized code for the index.js file:-

const express = require('express');
const mongoose = require('mongoose');

// set up our express app
const app = express();

// connect to mongodb
mongoose.connect('mongodb://localhost/ourdata');
mongoose.Promise = global.Promise;

app.use(express.static('public'));

app.use(express.json());
// initialize routes
app.use('/api',require('./routes/api'));

// error handling middleware
app.use(function(err,req,res,next){
    //console.log(err);
    res.status(422).send({error: err.message});
});

// listen for requests
app.listen(process.env.port || 4000, function(){
    console.log('Ready to Go!');
});
Enter fullscreen mode Exit fullscreen mode

The layout of the four CRUD operations

Next up, we create a folder named router and create a new file named api.js inside the folder. This would hold all the four CRUD operations we want to do with the REST API we are building.

We first start by requiring express in our file. Then we would create a router using the express router.

const express = require('express');
const router = express.Router();
Enter fullscreen mode Exit fullscreen mode

So, let’s start building the four operations one by one. Now, we would not be saving anything to the database since we have not created one yet, but we would be testing them more simply.
So, we would start with the GET operator. We will write the code for the GET request in this way:-

router.get('/students',function(req,res){
    res.send({type: 'GET'});
};
Enter fullscreen mode Exit fullscreen mode

Here, we are giving the endpoint and a function which gives a response which tells the type of the request sent.

Next up is POST request. It will be in a similar way though we would like to return the data which we received from the request.

router.post('/students', function(req, res){
    res.send({
        type: 'POST',
        name: req.body.name,
        roll: req.body.roll
    });
});
Enter fullscreen mode Exit fullscreen mode

Next up is PUT and DELETE request. For now, we would simply return the type of request for both the operations. It accepts the endpoint with an id which denotes the unique id which MongoDB provides when we save data to it.

router.put('/students/:id', function(req, res){
    res.send({type: 'PUT'});
});

router.delete('/students/:id', function(req, res){
    res.send({type: 'DELETE'});
});
Enter fullscreen mode Exit fullscreen mode

Next, we would export the module to be used within the index.js file.

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

To test out these operations, we would use a software called Postman. It is amazing and helps to test out APIs really fast.
Download the Postman desktop agent or install its Chrome extension to start using Postman. A Postman new Workspace looks like the following:-

Postman Workspace

Here, we can choose the type of operation and the target URL for sending requests. For POST requests, we need to send some JSON data while sending request which we can be done by adding the JSON in the Body section.

You need to select Raw data type and then chose JSON as the format such as shown below:-

Adding Body in Post request

So, we can test all these operations via Postman very easily. We also need to provide the data while PUT request as we are updating the data. We only pass the data we need to update.

Building the Database Schema and Model

Next, we would create a folder named models and then create a student.js file within that folder.

We would require mongoose in that folder and would build a Schema and then a model based on that Schema. A Schema tells the model how the data is to be structured.

We are building a model which would contain data of students — name, their roll number and whether they are present or not.

  1. Name — This is of String data type and is not a required field in the Schema.
  2. Roll — This is also of String data type and is a required field. It cannot be left empty.
  3. Present — This is a Boolean field which defaults to true.

We then create the model named Student with the help of the StudentSchema that we created. We then export the model to use it in the API file.

So, let’s have a look at the student.js file:-

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// create student schema & model
const StudentSchema = new Schema({
    name: {
        type: String,
    },
    roll: {
        type: String,
        required: [true, 'Roll field is required']
    },
    present: {
        type: Boolean,
        deafult: true
    }
});

const Student = mongoose.model('student',StudentSchema);
module.exports = Student;
Enter fullscreen mode Exit fullscreen mode

Finalizing the api.js file

Now, we would make all four API endpoints usable by saving and retrieving data from the database model we created.

So, we need to require that database model in the API file.

const Student = require('../models/student');
Enter fullscreen mode Exit fullscreen mode

We then start with the GET request. We would get all the students in our database and would send them all as a response. You can add any sort of filtering for the students but we are leaving the find function empty to access every student from the database. We then use .catch(next) function to help catch any errors and pass it to the next middleware — error handling middleware in our case.

router.get('/students',function(req,res,next){
    Student.find({}).then(function(students){
        res.send(students);
    }).catch(next);
});
Enter fullscreen mode Exit fullscreen mode

Next, we go for the POST request. We create a new student in the database and then return the created student as a response.

router.post('/students',function(req,res,next){
    Student.create(req.body).then(function(student){
        res.send(student);
    }).catch(next);
});
Enter fullscreen mode Exit fullscreen mode

Next, we have the PUT request. We would use the findOneAndUpdate function to find the corresponding entry in the database using the id we passed in the URL endpoint. We then find the same student with the help of its Id and return the updated student as a response.

router.put('/students/:id',function(req,res,next){
    Student.findOneAndUpdate({_id: req.params.id},req.body).then(function(student){
        Student.findOne({_id: req.params.id}).then(function(student){
            res.send(student);
        });
    });
});
Enter fullscreen mode Exit fullscreen mode

Lastly, we have the DELETE request. We use the function findOneAndDelete to find the corresponding student in the database via the id provided and delete that student from the database. It also returns the deleted student as a response.

router.delete('/students/:id',function(req,res,next){
    Student.findOneAndDelete({_id: req.params.id}).then(function(student){
        res.send(student);
    });
});
Enter fullscreen mode Exit fullscreen mode

We can test all these using the Postman software very easily. Everything should work fine on testing and we have done everything nicely and cleanly.

Here is the final code for the api.js file:-

const express = require('express');
const router = express.Router();
const Student = require('../models/student');

// get a list of students from the database
router.get('/students',function(req,res,next){
    Student.find({}).then(function(students){
        res.send(students);
    }).catch(next);
});

// add a new student to database
router.post('/students',function(req,res,next){
    Student.create(req.body).then(function(student){
        res.send(student);
    }).catch(next);
});

// update a student in the database
router.put('/students/:id',function(req,res,next){
    Student.findOneAndUpdate({_id: req.params.id},req.body).then(function(student){
        Student.findOne({_id: req.params.id}).then(function(student){
            res.send(student);
        });
    });
});

// delete a student in the database
router.delete('/students/:id',function(req,res,next){
    Student.findOneAndDelete({_id: req.params.id}).then(function(student){
        res.send(student);
    });
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

So, finally, we have created our REST API which performs all the four CRUD operations. So, as you see, it was very easy building a REST API with the help of Node, Express and MongoDB.

Discussion (0)

pic
Editor guide