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.
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
Create a Recipe
List all Recipes
Update Recipe
Delete a Recipe
Pre Req
Node & Npm installed.
Basic Knowledge of Node JS & environment setup.
MongoDB account for storing data.
Postman for API testing
Steps
Setting up Node JS app
Installing dependencies
Creating Server
Connecting to Mongo DB
Creating Recipe Model
Creating Routes (Create, Read, Update, Delete)
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
filecors => 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
Name (String)
Ingredients (Array)
Cuisine (String)
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/)