DEV Community

Cover image for 9 Steps to Build a RESTful API with Node.js, MongoDB, and Express
Shefali
Shefali

Posted on • Originally published at shefali.dev

9 Steps to Build a RESTful API with Node.js, MongoDB, and Express

In this post, I’ll guide you through the process of creating a simple RESTful API using Node.js, MongoDB, and Express.

Before starting, I’m assuming that you have Node.js, npm, MongoDB and VS Code installed on your machine.

If you haven’t yet, then you can check the following:

Let’s jump right into it!🚀

Step 1: Setting Up the Project

Let’s create a new project folder to get started. Open your terminal and run the following commands one by one.

mkdir my-first-restful-api
cd my-first-restful-api
Enter fullscreen mode Exit fullscreen mode

This will create a new directory in your machine.

RESTful API with Node.js, MongoDB, and Express
Now, let’s initialize our project by running the follwing command in the terminal (make sure you’re into your newly created project folder).

npm init
Enter fullscreen mode Exit fullscreen mode

The above command will walk you through creating a package.json file. Enter the details for the query and hit enter to go to the next query.

Or you can run the below command to create a package.json file with default settings.

npm init -y
Enter fullscreen mode Exit fullscreen mode

In the below image, I’ve used npm init command.

RESTful API with Node.js, MongoDB, and Express
After entering all the details a file named package.json will be created in your project folder as you can see in the below image.

package.json

Step 2: Installing Dependencies

Now let’s install the necessary packages for our project by running the following command in the terminal.

npm install express mongoose dotenv
Enter fullscreen mode Exit fullscreen mode

The above command will install

  • Express: For building the web server.
  • Mongoose: An ODM (Object Data Modeling) library for MongoDB.
  • dotenv: For loading environment variables from a .env file.

RESTful API
After running the above command, this should be the structure of your project folder.

RESTful API with Node.js, MongoDB, and Express

What is .env file and why we need it?

A .env file is used to store configuration variables, such as API keys, database credentials, and other sensitive information, separately from the codebase for security purpose.

Note: If you push your code to GitHub, then make sure you don’t push .env file, so that no one can access your sensitive information. You can do so by adding .env in your .gitignore file.

Step 3: Set Up a Basic Express app

Create a file named index.js in your root directory.

Node.js, MongoDB, and Express
Now, add the following code to the index.js file.

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

You might be wondering, do I have to remember the above code or from where this code has come?🤔

Let me tell you where you can find this code.

  • Go to expressjs.com
  • Hover over Getting started and click on Hello world.
  • You’ll find the code for the basic hello world example.

Express JS
Now, let’s run our server by the following command:

node index.js
Enter fullscreen mode Exit fullscreen mode

(For this command, I’ve used VS Code in-built terminal. You can use your machine’s terminal as well.)

This should be the output in your terminal.

node index.js
In your browser, if you go to localhost:3000 then you’ll see Hello world! on the page as follows.

Express Server
So, our server is running properly.

Step 4: Creating a MongoDB Database

In this step, we will create a Database on MongoDB Atlas.

  • Go to MongoDB Atlas and create an account or sign-in if you already have one.
  • If you’re creating a new account then it will ask you to create a username and password, so create those. Then in the second step choose “My Local Environment” and fill your IP address. After that click on “Finish and Close”.

MongoDB Database

  • Then go to Database (You’ll find on the left menu) and click on Create button (on the right side of the screen). Create a Free Shared Cluster.
  • Now on the home page of the cluster, click on connect button.

MongoDB
The following window will appear and then click on the Compass link.

MongoDB Cluster
Copy the connection string and replace <password> with your password which you’ve created before. Also install the MongoDB Compass if you haven’t yet.

Your connection string should look like this.

mongodb+srv://shefali:********@cluster0.sscvg.mongodb.net/
Enter fullscreen mode Exit fullscreen mode

In your connection string, instead of “shefali” this will display your username and instead of “********”, your password.

Step 5: Creating a .env file

To protect our mongoDB connection string, let’s create a new file named .env in the root directory.

RESTful API structure
Add the following code to the .env file.

MONGODB_URL=<Your MongoDB Connection String>
Enter fullscreen mode Exit fullscreen mode

Replace <Your MongoDB Connection String> with the connection string you obtained from MongoDB Atlas. Now your .env file should look like this.

MONGODB_URL=mongodb+srv://shefali:********@cluster0.sscvg.mongodb.net/my-first-restful-api
Enter fullscreen mode Exit fullscreen mode

In the above string, at last I’ve added my-first-restful-api which is our database name.

Step 6: Connecting to MongoDB using Mongoose

Add the following code to your index.js file to connect the mongoDB.

const mongoose = require('mongoose');
require('dotenv').config(); //for using variables from .env file.

mongoose.connect(process.env.MONGODB_URL).then(() => {
  console.log("MongoDB is connected!");
});
Enter fullscreen mode Exit fullscreen mode

Here process.env.MONGODB_URL will get the connection string from the .env file.

Your final code should look like the following:

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

require("dotenv").config(); //for using variables from .env file.

const app = express();
const port = 3000;

mongoose.connect(process.env.MONGODB_URL).then(() => {
  console.log("MongoDB is connected!");
});

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Now when you restart your server using node index.js command, your terminal output should be like this.

node index.js
Note: If you don’t see any changes, then make sure to restart your server.

In this step, we have successfully connected to MongoDB using mongoose.

Step 7: Defining a simple schema

Let’s create a simple schema for our project. (Know more about Schemas)

For this, create a new folder named model in your root directory and inside that folder create a file named todo.js.

MongoDB Schema
Add the following code to the todo.js file.

const mongoose = require("mongoose");
const { Schema } = mongoose;

const todoSchema = new Schema({
  title: {
    type: String
  },
  description: {
    type: String
  },
});

const Todo = mongoose.model("Todo", todoSchema);
module.exports = Todo;
Enter fullscreen mode Exit fullscreen mode

And import this model in your index.js file like this.

const Todo = require("./model/todo");
Enter fullscreen mode Exit fullscreen mode

Step 8: Implementing CRUD Operations

Let’s start creating routes for basic CRUD operations.

Create

Add the following code to the index.js file.

// Create an todo item
app.post("/todos/create", async (req, res) => {
  try {
    const newTodo = await Todo.create(req.body);
    res.status(201).json(newTodo);
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" });
  }
});
Enter fullscreen mode Exit fullscreen mode

In the above code,

  • There’s an HTTP POST endpoint /todos/create for creating a new todo item.
  • When a POST request is made to /todos/create, the code inside the async function is executed.
  • It uses the Todo.create method (All methods for models) to create a new todo item based on the data in the request body (req.body).
  • If the creation is successful, it responds with a status code 201 and sends the newly created todo item in JSON format as a response.
  • If there’s an error during the process, it catches the error and responds with a status code 500 and error message Internal Server Error.

In simpler terms, this code handles requests to create a new todo item. It tries to create the item, and if successful, it responds with the created item. If there’s an issue during the process, it responds with an error message.

Read

Replace the code of app.get to the following code in the index.js file.

// Read all todos
app.get("/todos", async (req, res) => {
  try {
    const todos = await Todo.find();
    res.status(200).json(todos);
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: "Internal Server Error" });
  }
});
Enter fullscreen mode Exit fullscreen mode

In the above code,

  • There’s an HTTP GET endpoint /todos for getting the todo items.
  • When a GET request is made to /todos, the code inside the async function is executed.
  • It uses the Todo.find method (All methods for models) to fetch all the todo items from the database.
  • If the fetching is successful, it responds with a status code 200 and sends all the todo items in JSON format as a response.
  • If there’s an error during the process, it catches the error and responds with a status code 500 and error message Internal Server Error.

Update

Add the following code to the index.js file.

// Update a todo by ID
app.put("/todos/:id", async (req, res) => {
  try {
    const updatedTodo = await Todo.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
    });
    res.status(200).json(updatedTodo);
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" });
  }
});
Enter fullscreen mode Exit fullscreen mode

In the above code,

  • There’s an HTTP PUT endpoint /todos/:id, where :id is a placeholder for a specific todo item’s id.
  • When a PUT request is made, it tries to update a todo in the database with the specified ID (req.params.id) using the Todo.findByIdAndUpdate method (All methods for models).
  • The new data for the todo is expected to be in the request body (req.body). This data is sent by the client making the PUT request.
  • The third argument { new: true } ensures that the method returns the updated todo after the update operation.
  • If the update is successful, it responds with a status 200 and sends the updated todo in JSON format in the response body.
  • If any error occurs during the update process (for example, if the specified ID is not found), it catches the error and responds with status 500 and error message Internal Server Error.

Delete

Add the following code to the index.js file.

// Delete a todo by ID
app.delete("/todos/:id", async (req, res) => {
  try {
    await Todo.findByIdAndDelete(req.params.id);
    res.status(204).send();
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" });
  }
});
Enter fullscreen mode Exit fullscreen mode

In the above code,

  • There’s an HTTP DELETE endpoint /todos/:id, where :id is a placeholder for a specific todo item’s id.
  • When a DELETE request is made, it tries to delete a todo in the database with the specified ID (req.params.id) using the Todo.findByIdAndDelete method (All methods for models).
  • If the deletion is successful, it responds with a status 204(No Content).
  • If any error occurs during the deleting process (for example, if the specified ID is not found), it catches the error and responds with status 500 and error message Internal Server Error.

Now, before testing our API, we need to add the following line of code to our index.js file, because we will read the data in JSON format.

//middleware provided by Express to parse incoming JSON requests.
app.use(express.json()); 
Enter fullscreen mode Exit fullscreen mode

Now, your index.js file should look like this.

const express = require("express");
const mongoose = require("mongoose");
const Todo = require("./model/todo");

require("dotenv").config(); //for using variables from .env file.

const app = express();
const port = 3000;

//middleware provided by Express to parse incoming JSON requests.
app.use(express.json());

mongoose.connect(process.env.MONGODB_URL).then(() => {
  console.log("MongoDB is connected!");
});

// Create an todo item
app.post("/todos/create", async (req, res) => {
  try {
    const newTodo = await Todo.create(req.body);
    res.status(201).json(newTodo);
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

// Read all todos
app.get("/todos", async (req, res) => {
  try {
    const todos = await Todo.find();
    res.status(200).json(todos);
  } catch (error) {
    console.log(error);
    res.status(500).json({ error: "Internal Server Error" });
  }
});

// Update a todo by ID
app.put("/todos/:id", async (req, res) => {
  try {
    const updatedTodo = await Todo.findByIdAndUpdate(req.params.id, req.body, {
      new: true,
    });
    res.status(200).json(updatedTodo);
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" });
  }
});

// Delete a todo by ID
app.delete("/todos/:id", async (req, res) => {
  try {
    await Todo.findByIdAndDelete(req.params.id);
    res.status(204).send();
  } catch (error) {
    res.status(500).json({ error: "Internal Server Error" });
  }
});

app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Step 9: Testing the API

By using the command node index.js, we have to restart our server each time. To avoid this you can install nodemon using the following command. This restarts the server automatically each time you make the changes to your file.

npm install -g nodemon
Enter fullscreen mode Exit fullscreen mode

Now run your server using the following command.

nodemon index.js
Enter fullscreen mode Exit fullscreen mode

nodemon index.js
For testing the API, I’m using the VS Code extension named Thunder Client. You can use Postman as well.

Let’s test our API now.

Create a new todo item using a POST request

In the Headers tab, add Content-Type to application/json, choose POST and write the URL like the image below.

CRUD RESTful API
In the Body tab, add title and description of the todo item as shown in the image.

CRUD RESTful API
After that, click on the Send button and you’ll get the following response.

CRUD RESTful API
We have successfully created our first todo item. You can create more todo items with different titles and descriptions using the same process.

You can also see these items in your MongoDB compass app as well after connecting with your connection string, like the below image.

MongoDB Compass

Get all todos using a GET request

For getting the todos, choose GET and write the URL like the image below and click on the Send button.

CRUD RESTful API
You’ll get the response as shown in the image.

CRUD RESTful API

Update a todo item using a PUT request

For updating the todo, we will need the id of the todo item. So copy the id of the todo which you got in the previous response.

Choose PUT and write the URL as shown in the image.

CRUD RESTful API
Now, in the Body tab, update the title and description.

CRUD RESTful API
Click on the Send button and you’ll get the below response.

CRUD RESTful API

Delete a todo item using a DELETE request

For deleting a todo item, choose DELETE and write the URL as shown in the image.

CRUD RESTful API
After clicking the Send button, you’ll get the following response.

CRUD RESTful API
Our todo item has been deleted.

Congratulations! 🎉

You’ve successfully created a RESTful API using Node.js, MongoDB, and Express.

That’s all for today.

I hope it was helpful.

Thanks for reading.

For more content like this, click here.

You can also follow me on X(Twitter) for getting daily tips on web development.

Keep Coding!!
Buy Me A Coffee

Top comments (6)

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
devshefali profile image
Shefali

Thank you so much, Andrew!

Collapse
 
darshangaikwad profile image
Darshan Gaikwad

Great! It's helpful to learn about RESTful APIs.

Collapse
 
devshefali profile image
Shefali

I'm happy this is helpful for you. Thanks for checking out, Darshan!

Collapse
 
devluc profile image
Devluc

Great article Shefali

Collapse
 
devshefali profile image
Shefali

Thank you so much Lucian!🙏