Tutorial: Build a RESTful API With CRUD Functionality Using Node.js, Express.js & MongoDB

Vakas Akhtar
The Startup
Published in
7 min readDec 7, 2020

--

Prerequisites

Before building your API make sure you have Node.js and MongoDB installed and setup on your machine before starting this tutorial. The complete code can be found here.

Initial Setup

Let’s get started by first opening up our terminal and creating a folder for our API. I chose to name my folder node-practice but feel free to name it whatever you’d like.

mkdir node-practice

Then cd into your folder and open it in your text editor. I’ll be using VSCode for this tutorial. Next initialize the package.json file.

npm init -y

Your package.json file will now look like this.

Next we’re going to install express mongoose to help us connect to MongoDB.

npm install express mongoose

If you look at your package.json you should now see express and mongo under your dependencies. Now install nodemon to ensure that we don’t have to restart the server every time we update our code.

npm install nodemon -D

After installing nodemon make sure you edit your scripts in your package.json file to include your nodemon dev dependencies. Your package.json file should look like this now.

{ "name": "node-practice", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "nodemon server" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1", "mongoose": "^5.11.5" }, "devDependencies": { "nodemon": "^2.0.6"  }}

Setting Up the Server

First create a file and name it server.js

touch server.js

Inside this file we’ll require express, create a route, and set a variable for the PORT that our server will use.

const express = require('express');const app = express();app.get('/', (req, res) => {
res.send('Hello World');
});
const PORT = process.env.PORT || 5000;app.listen(PORT, () => console.log(`Server running at port ${PORT}`));

Now if you run the server by entering the following command in your terminal you should see the “Hello World” text show up at http://localhost:5000/ :

npm run dev

MongoDB

Now it’s time for us to create our database! Hop on your browser and make your way over to MongoDB Atlas and create a new project. Once you’ve created your project you’ll have the option to build a cluster.

Select the button in the center to build a cluster

Once you’ve clicked the button you’ll be taken to this page:

Select the free option.

From this menu select the free option and continue on to the next steps in building your cluster.

Here in this menu you can select any location you’d like but for now, for the sake of simplicity do not change any of the other default options. For now I’ll choose N.Virginia and create my cluster after I complete my captcha questions and prove I’m not a robot.

Wait 3 minutes for your cluster to be created.

Now we wait for our cluster to be created. In the meantime let’s adjust some more settings. Head over to the network access tab on the left and select allow access from anywhere.

You can add a custom IP Address but for now we’ll allow access from anywhere

Once you’ve confirmed your network access it may take a minute or two to finalize this action. So let’s move on and click on the Database Access section. From here we’ll add a user that will be used when we connect to our Node backend.

Remember to copy and paste your username and password since we’ll need it later on.

From here you can create your own username and generate a secure password. Once you’ve generated your password make sure you copy it and keep it on the side since we’ll be using it very soon. Scroll down and you will see an option to create a user and you should be all set for the next step. Now is a good time to check that your cluster is created and that your Network Access status is active.

Perfect! Now go back to the clusters tab and select the option to connect.

You should see this pop up after clicking connect.

From here select the option to connect to your application

Make sure the driver is set to Node.js and select your desired version. Once your settings are good to go copy the url and return to your text editor.

From your terminal create a new file called config.js

touch config.js

Inside this file enter the following code and paste the url that you copied earlier into the code:

module.exports = {
MONGO_URI:`mongodb+srv://YOUR_USERNAME<password>@cluster0.qo3oa.mongodb.net/<dbname>?retryWrites=true&w=majority`
}

Inside the url where it says <password> paste in your password that you generated earlier. In the section <dbname> you can enter any name you would like.

Now let’s head back to the file server.js and make some changes to incorporate mongoDB. First we’ll add mongoose and import our MONGO_URI. Then we’ll remove the route that rendered “Hello World”. Your server.js file should now look like this.

const express = require('express');const mongoose = require('mongoose');const { MONGO_URI } = require('./config');const app = express();mongoose.connect(MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('MongoDB connected!'))
.catch(err => console.log(err));
const PORT = process.env.PORT || 5000;app.listen(PORT, () => console.log(`Server running at port ${PORT}`));

Models and Routes

Now it’s time to build out our routes and models. We’ll start by making a folder for our models

mkdir models

now inside the models folder create a file called Posts.js. Inside this file we’ll make the schema for the model.

//Filename: Posts.jsconst mongoose = require('mongoose');const Schema = mongoose.Schema;const PostSchema = new Schema({ title: {
type: String,
required: true,
},
body: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
}
});module.exports = mongoose.model('Posts', PostSchema)

Nice, now that our schema is set up and we’ve exported it lets make some routes. First make a folder called routes and inside the folder make another folder called api. Now inside your api folder create a file called posts_controller.js. Inside this file enter the following code.

const express = require('express');
const router = express.Router();
const Posts = require('../../models/Posts');module.exports = router;

Now that we’ve brought over our server, router, and model we can start building out our CRUD functionality. Before we move on let’s go back to our server.js file. Here we are going to add in our routes. When the user reaches http://localhost:5000/ they will be able to access posts_controller.js file which has all the routes.

const express = require('express');const mongoose = require('mongoose');const { MONGO_URI } = require('./config');const postsRoutes = require('./routes/api/posts_controller')const app = express();
app.use(express.json());
mongoose.connect(MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('MongoDB connected!'))
.catch(err => console.log(err));
app.use('/api/posts', postsRoutes);const PORT = process.env.PORT || 5000;app.listen(PORT, () => console.log(`Server running at port ${PORT}`));

CRUD

Now we can start building out our CRUD functionality! Below I’ll insert the code snippets for each action inside our posts_controller.js file. Remember we’ll be starting from below the line where we declared our variable for the Posts model.

const express = require('express');
const router = express.Router();
const Posts = require('../../models/Posts');//your CRUD actions code go here module.exports = router;

Create:

router.post('/', async (req, res) => {const newPost = new Posts(req.body);try {const post = await newPost.save();if(!post) throw Error('Something went wrong with the post')res.status(200).json(post);} catch {res.status(400).json({msg: error})}});

Read:

Get all posts

router.get('/', async (req, res) => {try {const posts = await Posts.find();if(!posts) throw Error('No Items');res.status(200).json(posts);}catch(err) {res.status(400).json({mesg: err})}});

Show one post

router.get('/:id', async (req, res) => {try {const post = await Posts.findById(req.params.id);if(!post) throw Error('No Items');res.status(200).json(post);}catch(err) {res.status(400).json({mesg: err})}});

Update:

router.patch('/:id', async (req, res) => {try {const post = await Posts.findByIdAndUpdate(req.params.id, req.body);if(!post) throw Error('Something went wrong while updating the post');res.status(200).json({success: true});}catch(err) {res.status(400).json({msg:err});}});

Delete:

router.delete('/:id', async (req, res) => {try {const post = await Posts.findByIdAndDelete(req.params.id);if(!post) throw Error('No post found!');res.status(200).json({success: true})}catch(err) {res.status(400).json({msg: error})}});

Final Thoughts:

Now that your API is all ready to go you can test it out yourself using Postman with the url http://localhost:5000/api/posts. The complete code for this blog can be found here.

--

--