Create a CRUD API in nodejs, expressjs and mongoDB

In this tutorial, we'll see how to create a simple crud api in express js and mongoose. Here we'll create five endpoints and will also test them by using software called postman. So let's get started by creating a new node project.

Create a new Project

mkdir crud-api
cd crud-api
npm init
npm i express mongoose

Setup a basic express server

First, create a new directory named config and add an index.js file that will carry all the various settings of our project like Db Url, port, etc. (Note: the recommended way to store the info like DB URL, secret keys are inside the .env file and loading it using the dotenv module.)

config/index.js
module.exports = {
    DB_URL: 'mongodb+srv://user1:user5@cluster0.12345.mongodb.net/yuo?retryWrites=true&w=majority'
}

Now let's set up an express server and connect it to our mongo database and listen at port 8000.

app.js
const express = require("express");
const mongoose = require("mongoose");
const config = require('./config')

const app = express();

// Connect with the mongo db
try{
    mongoose.connect(config.DB_URL,
        { useNewUrlParser: true ,useUnifiedTopology: true},
        ()=>{console.log("DB Connected")})
}catch(err){
    console.log(err)
}

// Parse the request body
app.use(express.json());
app.use(express.urlencoded({
  extended: true
}));

const PORT = 8000
app.listen(PORT, ()=>console.log(`Listening at port ${PORT}`))

Create Article Model

Let's create a model named 'Article' with only two string fields(title and body).

models/article.js
const mongoose = require('mongoose')

const articleSchema = mongoose.Schema({
    title: String,
    body: String
})
    
module.exports = mongoose.model('Article' ,articleSchema)

Create Article Controllers

It's time to create the controllers that will keep the business logic of our crud api. For now, I'm just creating five empty functions that take request and response as arguments and will explain them one by one in the next section.

controllers/articleController.js
const Article = require('../models/article')

module.exports = {
    // Get all the articles
    getAll: async (req, res) => {

    },

    // Get a single article having a given ID
    getSingle: async (req, res) => {
        
    },

    // Create a new article
    create: async (req, res) => {

    },

    // Update a article of given id
    update: async (req, res) => {

    },

    // Delete a article of given id
    delete: async (req, res) => {

    }

}

Get all articles

This function simply fetches all the articles from the database and returns them as a JSON response.

    // Get all the articles
    getAll: async (req, res) => {
        let allArticles = await Article.find({});
        res.json({
            okay: true,
            msg: "success",
            data: allArticles
        })
    },

Get single article

First, we try to fetch the article with the given id and then return 404 if not found else return the article data to the user.

    // Get a single article with a given ID
    getOne: async (req, res) => {

        // Find the article
        let article = await Article.findById(req.params.id)

        // Return 404 if article not found
        if(!article){
            return res.status(404).json({
                okay: false,
                msg: `Article with id ${req.params.id} not found`,
                data: {}
            })
        }

        return res.json({
            okay: true,
            msg: "success",
            data: article
        })

    },

Create a new article

In this function, we create and return the new article entry after checking the user input.

    // Create a new article
    create: async (req, res) => {
        // If req body does not have title or body
        if(!(req.body.title && req.body.body)){
            return res.status(400).json({
                okay: false,
                msg: "Incomplete Data",
                data: {}
            })
        }

        // Create a new article
        let newArticle = await Article.create({
            title: req.body.title,
            body: req.body.body
        })

        res.json({
            okay: true,
            msg: "success",
            data: newArticle
        })
    },

Update a article

Here first we check if the user provides any data or not, then try to update the article and return the previous article data to the user.

    // Update a article of given id
    update: async (req, res) => {

        // Check if user provided any data to be updated
        if(!req.body){
            return res.status(400).json({
                okay: false, 
                msg: "Please provide the data to be updated"
            })
        }

        // Update the article
        let article = await Article.findByIdAndUpdate(req.params.id, req.body)

        // Return 404 if article not found
        if(!article){
            return res.status(404).json({
                okay: false,
                msg: `Article with id ${req.params.id} not found`,
                data: {}
            })
        }

        return res.json({
            okay: true,
            msg: "success",
            data: article
        })

    },

Delete a article

In this function, we just delete the article of given id and return the data to the user.

    // Delete a article of given id
    delete: async (req, res) => {

        // delete the article
        let article = await Article.findByIdAndDelete(req.params.id)

        // Return 404 if article not found
        if(!article){
            return res.status(404).json({
                okay: false,
                msg: `Article with id ${req.params.id} not found`,
                data: {}
            })
        }

        return res.json({
            okay: true,
            msg: "success",
            data: article
        })
    }

Create Routes

At last, it's time to create and connect the api routes to the controller functions. All this code should be inside the routes/articleRoutes.js file.

routes/articleRoutes.js
const router = require("express").Router();
const controller = require("../controllers/articleController");

// Get all articles
router.get("/", controller.getAll)

// Create a new article
router.post("/", controller.create)

// Retrieve a single article of given id
router.get("/:id", controller.getOne)

// update a single article of given id
router.put("/:id", controller.update)

// delete a single article of given id
router.delete("/:id", controller.delete)

module.exports = router;

Also, we need to add the above routes to our server file.

app.js
// Rest of the code is same

// Article routes
app.use('/api/articles', require("./routes/articleRoutes"))

const PORT = 8000
app.listen(PORT, ()=>console.log(`Listening at port ${PORT}`))

Testing of API

Finally, it's time to run the server and test the integration using the postman.

node app.js
Create a new article
Create New
Get a single article
Get One
Get all articles
Get All
Update a article
Update One
Delete a article
Delete One