Mastering Backend Development: Building a Feature-Rich CRUD System with Node.js, Express, and MongoDB

Follow on LinkedIn

In this article, we are building a complete CRUD system with node.js, Express, and MongoDB. We are using mongoDBCompass for viewing our Mongo database and Postman to execute our queries.

In this CRUD system, we are creating APIs for creating a course, fetching all course data, fetching course data based on course id, and updating and deleting the course based on its id.

Let’s start building this, firstly we need to install node.js on our computer, so go to https://nodejs.org/en and download the recommended version.

Once you download the node.js and installed it on your computer, we can start working on our project.

Now, create a folder called course-project, you can name it whatever you want, move inside this folder, and initialize your package.json file by running this command.

npm init -y

This command will initialize the package.json file with all default options, as we are passing a -y flag to initialize all default properties.

if we do not pass -y then during the installation it will ask for the basic details of the package.json file and you have to write all the details, for now, we are ok with all default options.

After the initialization of the package.json file, we need to install the express inside our directory, and for that, we need to run the below command.

npm install express

This command will install express inside your course-project directory and will create a folder node_modules that has all the package.json file modules and express required modules installed in it.

Now, one more thing we need in our project is Babel, because Babel allows us to write modern JavaScript code and transform it into compatible versions that can run in different environments.

To install all required components of Babel, we need to run this command.

npm i --save-dev @babel/core @babel/cli @babel/node @babel/preset-env

After installing all the components of Babel, now we will create a .babelrc file inside our root directory and set it like the below code.

{
  "preset":["@babel/preset-env"]
}

We don’t want to re-run our code every time we made any changes, to re-run our code automatically on saving files, we need a hot reloading feature, and for that, we can use Nodemon.

Nodemon automatically restarts the application whenever changes are detected in the source code.

To install Nodemon, run the below command inside the terminal.

npm install nodemon

Installing Nodemon is not enough, we need to set our command inside the package.json file like below.

"scripts": {
  "start": "nodemon ./index.js --exec babel-node"
},

Now the server will automatically restart whenever there is a change detected in the source file by the node.

you can run the npm start command to run the above command.

Two more packages we need to install inside this project to successfully run it are mongoose and body-parser, here is the command for both.

npm install mongoose
npm install body-parser

Mongoose is an Object-Document Mapping (ODM) library for MongoDB and Node.js, it provides a way to interact with MongoDB by defining schemas and models, performing database operations, and handling data validation.

Body-parser is a middleware package for parsing HTTP request bodies in Node.js, It extracts data from incoming requests and makes it accessible in the req.body object. It supports various formats, including URL-encoded, JSON, and multipart form data.

Now, let’s create the necessary files for this project.

Create an index.js in the root directory, one src folder, and one public folder, inside the src folder we will create three more folders, controllers, models, and routes.

Inside the controllers folder create a file called courseController.js, inside models create a file courseModel.js and inside the routes, folder create a file called courseRoutes.js

Now, we have all the files ready, let’s start with the index.js file.

import express from 'express';
import mongoose from 'mongoose';
import routes from './src/routes/courseRoutes';
import bodyParser from 'body-parser';
const app=express();
const PORT = 3000;
//mongoose connection
mongoose.Promise=global.Promise;
mongoose.connect('mongodb://localhost/courseDB',{
useNewUrlParser:true
})
//body parser setup
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
routes(app);

//serving static files
app.use(express.static('public'));

app.get('/',(req,res)=>{
    res.send(`<h1>Project Working at </h1> ${PORT}`);
})
app.listen(PORT,()=>{
    console.log("server running");
});

Inside this index.js file, we are importing express, mongoose, routes, and body-parser.

import express from 'express';
import mongoose from 'mongoose';
import routes from './src/routes/courseRoutes';
import bodyParser from 'body-parser';

express: This is the express package we installed to create an express application and to handle HTTP requests.

mongoose: This will allow us to interact with the database.

routes: This is our courseRoutes.js file inside our routes folder that will contain the route handlers for different endpoints.

body-parser: This we can use to see the request body data passing to an API.

The below code will create an instance of express and another one is setting a port for application.

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

After the above code, we are setting the MongoDB connections.

//Setting the default Promise library for Mongoose to the global Promise
mongoose.Promise=global.Promise;

//Connect to the MongoDB database named "courseDB" 
//running on localhost using the mongoose.connect method.
mongoose.connect('mongodb://localhost/courseDB',{
useNewUrlParser:true
})

Here we are connecting with MongoDB database using Mongoose.

Mongoose is a library that simplifies working with MongoDB. This code connects to a local MongoDB database named courseDB.

Now, let’s talk about body-parser.

The body-parser middleware is used to parse incoming request bodies in a middleware before handling them. In this case, it is configured to handle both URL-encoded data and JSON data.

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

One another line of code that is very important to understand.

routes(app);

This line sets up the routes defined in the courseRoutes module and passes the Express app instance to it.

The rest of the code is just normal express code to listen express app and check the port status and also, how you can define a path for your static files.

Now, let’s move to the controller, model, and routes files.

import mongoose from "mongoose";
const Schema=mongoose.Schema;
export const CourseSchema = new Schema({
    courseName:{
        type:String,
        required:'Enter your course name'
    },
    courseDisc:{
        type:String,
        required:'Enter your course description'
    },
    email:{
        type:String
    },
    created_date:{
        type:Date,
        default:Date.now
    }
});

Inside the models folder, we have a file courseModel.js, In this file, we are importing Mongoose and defining our Course Schema for the database.

Now, we have the controllers folder, inside this folder, we have a file called courseController.js, This file has all the functions to operate on Course Scheme defined inside the courseModel.js file.

Here, first, we import this courseModel.js file Schema with the name CourseSchema, we will also import Mongoose.

import mongoose from "mongoose";
import { CourseSchema } from "../models/courseModel";
const Course = mongoose.model('Course',CourseSchema);


export const addNewCourse = async (req, res) => {
    try {
      const newCourse = new Course(req.body);
      const savedCourse = await newCourse.save();
      res.send(savedCourse);
    } catch (error) {
      res.send(error);
    }
  }

  export const getCourses = async (req, res) => {
    try {
      const Courses = await Course.find({}).exec(); 
      res.json(Courses);
    } catch (error) {
      res.send(error);
    }
  }

  export const getCourseById = async (req, res) => {
    try {

      const CourseId = req.params.CourseId;

      const Course = await Course.findById(CourseId).exec();
      console.log("requstnew",Course)

      if (!Course) {
        return res.status(404).json({ error: 'Course not found' });
      }
  
      res.json(Course);
    } catch (error) {
      res.send(error);
    }
  };

  export const updateCourse = async (req, res) => {
    try {
      const CourseId = req.params.CourseId;
      const updatedCourse = req.body; // Updated Course data from the request body
  
      const Course = await Course.findByIdAndUpdate(CourseId, updatedCourse, {
        new: true, // Return the updated Course after the update operation
      }).exec();
  
      if (!Course) {
        return res.status(404).json({ error: 'Course not found' });
      }
  
      res.json(Course);
    } catch (error) {
      res.send(error);
    }
  };
  
  export const deleteCourse = async (req, res) => {
    try {
      const CourseId = req.params.CourseId;
  
      const deletedCourse = await Course.findByIdAndRemove(CourseId).exec();
  
      if (!deletedCourse) {
        return res.status(404).json({ error: 'Course not found' });
      }
  
      res.json({ message: 'Course deleted successfully' });
    } catch (error) {
      res.send(error);
    }
  };

Now by using async, await, and try catch, we will define our functions to do multiple operations like getting all course data, getting course data by id, adding new course data, updating course data by id, and deleting course data by id.

But we are not hitting any API inside this file, these are the functions to perform operations on a database, To send a request to an API we have another file courseRoutes.js inside the routes folder.

import { addNewCourse, getCourses, getCourseById, updateCourse, deleteCourse } from "../controllers/courseController";
const routes=(app)=>{
    app.route('/Course')
    .get((req,res,next)=>{
        //middelware
        console.log(`Request From: ${req.originalUrl}`);
        console.log(`Request Type: ${req.method}`);
        next();
    },getCourses)

    .post(addNewCourse)

    app.route('/Course/:CourseId')

    .get((req,res,next)=>{
        //middelware
        console.log(`Request From: ${req.originalUrl}`);
        console.log(`Request Type: ${req.method}`);
        next();
    },getCourseById)

    .put(updateCourse)
    .delete(deleteCourse)
}

export default routes;

Inside this file, we are importing all the functions defined inside the courseController.js file.

Using app.route we are accessing all the methods like get, post, put, and delete and by passing on methods from the controller file, here we are performing operations of CRUD on the database.

I hope you get the understanding of creating a basic CRUD operation on MongoDB database with express and node.

Let me show you how you will connect with the local database.

First, you need to download the MongoDBCompass from this link https://www.mongodb.com/products/compass

After downloading and installing it, you will see this screen.

Now, when you click on connect your database will be connected to your application and you can perform the operations, it will automatically create a database for your application with the name you defined inside the Mongoose connections in the index.js file.

Below you can see the connected database.

I hope you like this article, Thankyou for reading it, Happy Coding 🙂

Related Posts

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

×