How to build CRUD APIs in NodeJS & MongoDB?

How to build CRUD APIs in NodeJS & MongoDB?

Here’s the tutorial for building CRUD APIs (CREATE, READ, UPDATE, DELETE) for absolute beginners with complete code.

·

6 min read

In this tutorial, you will learn to build CRUD APIs (Create, Read, Update, Delete) in Node JS. We’ll create CRUD APIs for a Recipe App.

Features of the Recipe App

  1. Create a Recipe

  2. List all Recipes

  3. Update Recipe

  4. Delete a Recipe

Pre Req

  1. Node & Npm installed.

  2. Basic Knowledge of Node JS & environment setup.

  3. MongoDB account for storing data.

  4. Postman for API testing

Steps

  1. Setting up Node JS app

  2. Installing dependencies

  3. Creating Server

  4. Connecting to Mongo DB

  5. Creating Recipe Model

  6. Creating Routes (Create, Read, Update, Delete)

  7. Testing APIs using Postman

    Setting up Node JS App

    Let’s create a folder for our app.

    mkdir recipe-app
    

    Navigate to folder

    cd recipe-app
    

    Initialize Node JS project

    npm init -y
    

    This will create package. json in a recipe-app folder.

    Install Dependencies

     npm install mongoose express dotenv cors nodemon
    

    express => It’s a NodeJS framework that allows to setup of middleware to respond to HTTP Requests.

    mongoose => Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment

    dotenv => module that loads environment variables from a .env file

    cors => it’s used for enabling cors

    nodemon => it is a tool that helps develop Node. js applications by automatically restarting the node application when file changes in the directory are detected.

    Add nodemon to package.json

    {
      "name": "recipe-app",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "nodemon index.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "cors": "^2.8.5",
        "dotenv": "^16.0.3",
        "express": "^4.18.2",
        "mongoose": "^6.8.0",
        "nodemon": "^2.0.20"
      }
    }
    

    Creating Server

    We’ll create a root file where we’ll create an express server.

    Create an index.js file in the root file

    const express = require("express");
    
    const PORT = 3000;
    
    const app = express();
    
    app.listen(PORT, async () => {
      console.log(`Server Listeining on ${PORT}`);
    });
    

    This will create a server that listens on PORT 3000

    Now run this command to start the app

    npm start
    

    This will start our server which is running on port 3000

    Connecting to MongoDB

    If you don’t have MongoDB, you can set it up by following this local or cloud.

    Create a .env file in your root folder

    Copy your MongoDB connection string from the local MongoDB or MongoDB atlas & paste it in the .env file

    MONGO_DB_STRING= paste your mongo string here
    

    Now create a file called db.js in the root folder, and add the following code into it.

    const mongoose = require('mongoose');
    require('dotenv').config()
    module.exports = () =>
      new Promise(async (resolve, reject) => {
        try {
          // Connect to MongoDB
          mongoose.set('strictQuery',false);
          const URL = process.env.MONGO_DB_STRING
          await mongoose.connect(URL);
    
          console.log('MongoDB Connected...');
    
          resolve(true);
        } catch (error) {
          console.log('MongoDB Connection Error: ', error);
          reject(error);
        }
      });
    

    import db.js file into index.js to connect our app to MongoDB

    const express = require("express");
    const PORT = 3000;
    const app = express();
    const db=require('./db');
    
    db()
    
    app.listen(PORT, async () => {
      console.log(`server up on port ${PORT}`);
    });
    

    Now check if it works, run npm start in your console. This is how it should look

    Create Recipe Model

    We’ll define our recipe collection in our Recipe model. Create a folder model in the root, inside of it create a file models/Recipe.js.

    The recipe collection will have the following fields

    1. Name (String)

    2. Ingredients (Array)

    3. Cuisine (String)

    4. timestamp

```bash
const mongoose = require("mongoose");

const RecipeSchema = new mongoose.Schema({
  Name: {
    type: String,
    required: true,
  },
  Ingredients: {
    type: Array,
    required:true
  },
  Cuisine: {
    type: String,
    required:true
  }
},{timestamps:true});

module.exports = mongoose.model("recipe", RecipeSchema);
```

## Creating Routes

Create a folder called routes, and create a file index.js inside of it. Add the following code to it.

```bash
const express=require('express')
//import router to create routes
const router = express.Router();
```

Express router will let us create HTTP requests for CRUD.

**If you’re not already familiar with HTTP Methods, here’s a little peek into it.**

1.  *POST (it’s used t*o create new data)


*2\. GET (For retrieving data)*

*3\. PUT (it’s used for updating data)*

*4\. DELETE (As the name applies, it’s used for deleting data)*

#### Add a Recipe

Let’s create a POST route for adding recipes.

```bash
//add recipe
router.post('/', function(req, res, next) {
    try {
        const {Name,Ingredients,Cuisine}=req.body;
        const newRecipe=new RecipeModel({Name,Ingredients,Cuisine})
        newRecipe.save();

        return res.status(200).send({message:"Data has been added!",data:newRecipe})

    } catch (error) {
        return res.status(400).send({message:"Error Occured!",error:error.message})
    }
});
```

#### List all Recipes

```bash
/* GET recipe listing. */
router.get('/', function(req, res, next) {
    try {
        const recipes= RecipeModel.find({});
        return res.status(200).send({message:"Data has been added!",data:recipes})
    } catch (error) {
        return res.status(400).send({message:"Error Occured!",error:error.message})
    }
});
```

#### Update a Recipe

```bash
//update recipe
router.put('/:recipeId', function(req, res, next) {
    try {
        const recipeId= req.params.recipeId;
        const {Name,Ingredients,Cuisine}=req.body;
        RecipeModel.findByIdAndUpdate(recipeId,{Name,Ingredients,Cuisine})

        return res.status(200).send({message:"Recipe has been updated!"})

    } catch (error) {
        return res.status(400).send({message:"Error Occured in update!",error:error.message})
    }
});
```

#### Delete Recipe

```bash
//delete recipe
router.delete('/:recipeId', function(req, res, next) {
    try {
        const recipeId= req.params.recipeId;
        RecipeModel.findByIdAndDelete(recipeId)

        return res.status(200).send({message:"Recipe has been updated!"})

    } catch (error) {
        return res.status(400).send({message:"Error Occured in update!",error:error.message})
}});
```

Here’s the full routes/index.js file

```bash
var express = require('express');
var router = express.Router();
//import recipe model
const RecipeModel=require('../models/Recipe');

/* GET recipe listing. */
router.get('/', function(req, res, next) {
    try {
        const recipes= RecipeModel.find({});
        return res.status(200).send({message:"Data has been added!",data:recipes});
    } catch (error) {
        return res.status(400).send({message:"Error Occured!",error:error.message});
    }
});

//add recipe
router.post('/', function(req, res, next) {
    try {
        const {Name,Ingredients,Cuisine}=req.body;
        const newRecipe=new RecipeModel({Name,Ingredients,Cuisine});
        newRecipe.save();

        return res.status(200).send({message:"Data has been added!",data:newRecipe});

    } catch (error) {
        return res.status(400).send({message:"Error Occured!",error:error.message});
    }
});

//delete recipe
router.delete('/:recipeId', function(req, res, next) {
    try {
        const recipeId= req.params.recipeId;
        RecipeModel.findByIdAndDelete(recipeId);

        return res.status(200).send({message:"Recipe has been updated!"});

    } catch (error) {
        return res.status(400).send({message:"Error Occured in update!",error:error.message});
}});

//update recipe
router.put('/:recipeId', function(req, res, next) {
    try {
        const recipeId= req.params.recipeId;
        const {Name,Ingredients,Cuisine}=req.body;
        RecipeModel.findByIdAndUpdate(recipeId,{Name,Ingredients,Cuisine});

        return res.status(200).send({message:"Recipe has been updated!"});

    } catch (error) {
        return res.status(400).send({message:"Error Occured in update!",error:error.message});
    }
});

module.exports = router;
```

Now import this in the root index.js file

```bash
const indexRouter=require('./routes/index');
app.use('/', indexRouter);
```

we’ll add middleware to our app which will parse incoming JSON requests and put the parsed data in `req.body`

```bash
app.use(express.json());
```

If we don’t use middleware POST API will throw an error.

![](https://cdn-images-1.medium.com/max/917/1*7ThmyaQO1YD-p07r5Lb1oA.png align="left")

Here’s the complete index.js file

```bash
const express = require("express");
const PORT = 3000;
const app = express();
const db=require('./db');
db()
const cors = require("cors");
app.use(cors())
app.use(express.json());
const indexRouter=require('./routes/index')

app.use('/', indexRouter);


app.listen(PORT, async () => {
  console.log(`Server Listeining on ${PORT}`);
});
```

## Testing APIs

We’ll use Postman to test our APIs, **Postman** is an API platform for developers to design, build, test and iterate their APIs.

Start your app using

```bash
npm start
```

You can listen to your app here [http://localhost:3000/](http://localhost:3000/)

Here's a link to postman APIs documentation

#### Create Recipe API

![](https://cdn-images-1.medium.com/max/917/1*7-rRGZ7pnVMK9exMwvmlhw.png align="left")

#### List Recipes

![](https://cdn-images-1.medium.com/max/917/1*HwVL5UNu-BrwKIeUmJ-HUg.png align="left")

#### Update Recipe

![](https://cdn-images-1.medium.com/max/917/1*EWwLxdgtN-eKbCBqBkAJYA.png align="left")

#### Delete a recipe

![](https://cdn-images-1.medium.com/max/917/1*3zqSXiVa2cTzzLzabggCVg.png align="left")

Here’s the complete code https://github.com/AtiaK/recipe-app

> *Did you find it helpful?*

*Let me know if you found this helpful or need any help.*

*Subscribe* [***here***](https://medium.com/subscribe/@atiazulfiqar) *to be on my email list to be notified of my new exciting blogs.*

> *Follow me on* [***Instagram***](https://www.instagram.com/codewithatia/)***,*** [***GitHub***](https://github.com/AtiaK)**,** [**LinkedIn**](https://www.linkedin.com/in/web-developer-mobile-app-developer/)