Building a Basic CRUD API with Node.js, MongoDB, and Express.js: A Beginner's Tutorial
Tags: tutorial, node, mongodb, beginners
Published: 2023-04-06 09:18:22

In this tutorial, we will be building a basic CRUD (Create, Read, Update, Delete) API using Node.js, MongoDB, and Express.js. A CRUD API is a fundamental part of most web applications, as it allows users to interact with and manipulate data stored in a database.

We will start by setting up a new Node.js project and installing the required dependencies, including Express.js and Mongoose, an Object-Document Mapper (ODM) for MongoDB. We will then connect to our MongoDB database and define a data model for our users collection.

Next, we will create API endpoints using Express.js for all four CRUD operations, including creating a new user, retrieving all users, retrieving a single user, updating a user, and deleting a user.

This tutorial is aimed at beginners who are new to Node.js, MongoDB, and Express.js. By the end of this tutorial, you should have a good understanding of how to build a basic CRUD API and how to interact with a MongoDB database using Mongoose. Let's get started!

Before we start, let me explain what CRUD means:

C: **Create** - Add a new item to the database
R: **Read** - Retrieve an item from the database
U: **Update** - Modify an existing item in the database
D: **Delete** - Remove an item from the database

To create a basic CRUD API, we will follow the steps below:

## Step 1: Install Required Dependencies

First, we need to create a new folder and setup Node.js project and install the required dependencies. 
Run the following command in your terminal:

`mkdir nem-crud && cd nem-crud`

Then run:
`npm init -y`

This command will create a new Node.js project with a package.json file.

Next, we will install the following dependencies:

express: A popular Node.js web framework
mongoose: An Object-Document Mapper (ODM) for MongoDB
To install these dependencies, run the following command:

`npm install express mongoose`

## Step 2: Connect to MongoDB

Next, we need to connect to our MongoDB database using Mongoose. To do this, create a new file called `db.js` in your project's root directory and add the following code:

```javascript
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/my_database', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('MongoDB connected...'))
.catch(err => console.log(err));
```
In the above code, we first import the `mongoose` module and then connect to our MongoDB database using the `mongoose.connect()` method. We also pass some options to the `mongoose.connect()` method, which are necessary for avoiding deprecation warnings. Finally, we log a message to the console to confirm that we have connected to the database.

Note: Make sure to replace **my_database** with the name of your own MongoDB database.

## Step 3: Define a Model

Next, we need to define a model for our data. In this example, we will create a model for `users`. To do this, create a new file called `user.js` in your project's root directory and add the following code:

```javascript
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  password: String
});

const User = mongoose.model('User', userSchema);

module.exports = User;
```

In the above code, we first import the `mongoose` module and then define a schema for our `users` collection. The schema defines the structure of the data in our collection. In this example, we have defined three fields: `name`, `email`, and `password`.

After defining the schema, we create a `User` model using the `mongoose.model()` method and export it so that we can use it in our API.

## Step 4: Create API Endpoints

Next, we need to create our API endpoints using Express.js. In this example, we will create endpoints for all four CRUD operations. To do this, create a new file called `app.js` in your project's root directory and add the following code:

```javascript
const express = require('express');
const User = require('./user');

const app = express();
app.use(express.json());

// Get all users
app.get('/users', async (req, res) => {
  try {
    const users = await User.find();
    res.json(users);
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

// Get a single user
app.get('/users/:id', getUser, (req, res) => {
  res.json(res.user);
});

// Create a new user
app.post('/users', async (req, res) => {
  const user = new User({
    name: req.body.name,
    email: req.body.email,
    password: req.body.password
  });

  try {
    const newUser = await user.save();
    res.status(201).json(newUser);
  } catch (err) {
    res.status(400).json({ message: err.message });
  }
});

// Update a user
app.patch('/users/:id', getUser, async (req, res) => {
  if (req.body.name != null) {
    res.user.name = req.body.name;
  }

  if (req.body.email != null) {
    res.user.email = req.body.email;
  }

  if (req.body.password != null) {
    res.user.password = req.body.password;
  }

  try {
    const updatedUser = await res.user.save();
    res.json(updatedUser);
  } catch (err) {
    res.status(400).json({ message: err.message });
  }
});

// Delete a user
app.delete('/users/:id', getUser, async (req, res) => {
  try {
    await res.user.remove();
    res.json({ message: 'User deleted' });
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
});

// Middleware function to get a single user by ID
async function getUser(req, res, next) {
  let user;
  try {
    user = await User.findById(req.params.id);
    if (user == null) {
      return res.status(404).json({ message: 'Cannot find user' });
    }
  } catch (err) {
    return res.status(500).json({ message: err.message });
  }

  res.user = user;
  next();
}

app.listen(3000, () => console.log('Server started...'));
```
In the above code, we first import the `express` module and our `User` model. We then create a new instance of `express` and use `express.json()` middleware to parse incoming JSON data.

Next, we define our API endpoints using the following HTTP methods:

GET: Used to retrieve data
POST: Used to create data
PATCH: Used to update data
DELETE: Used to delete data

For each endpoint, we define a URL path and a callback function that handles the incoming requests and sends back the appropriate responses.

We also define a middleware function called `getUser` that retrieves a single user by ID and sets it as a property of the response object. This function is used by the `GET`, `PATCH`, and `DELETE` endpoints to retrieve and manipulate a single user.
## Step 5: Start the Server
To start the server run `npm start` in your terminal.

Finally, we start the server listening on port 3000 and log a message to the console to confirm that the server has started.