You are currently viewing CRUD Operations in Node JS using Mongoose – Building Chart of Accounts

CRUD Operations in Node JS using Mongoose – Building Chart of Accounts

In one of my previous posts, I setup an express server in node.js and wrote controller and router. In this post, I will be using the same code repository and will build on top of it. This post is practical demonstration of the following:-

  • Setting up database – Creation of Collection and Documents in mongodb
  • Connect with the database, in our case the database is mongodb.
  • Create Model for chart of accounts
  • Person controller and Person router will be deleted and charts of accounts will take its place.

In order to understand the above, please visit the previous post, which is given below:-

Building a RESTful API with Express.js: Adding GET, POST, PUT, and DELETE Endpoints

Setting Up Database

In order to setup database, first we need to install the required database, which in my case is mongodb. Instead of installing it on my machine, I have utilized the mongo docker image from the docker hub. For that purpose, I have pulled the mongodb docker image from the docker hub. Once its available, I used the following command to run a container from the image. The command to run the mongodb container from the image is given below:-

Building a RESTful API with Express.js: Adding GET, POST, PUT, and DELETE Endpoints

shahid@shahid-VirtualBox:~$ sudo docker run -d --name mongodb -p 27017:27017 mongo

If above command is executed successfully it will return the id of the container which is created. I can use the docker command to see the status of the running container, but instead of that, I will use a GUI tool named “MongoDB Compass”.

I will use the same information which I provided to run the docker container to the MongoDB Compass to see if the connection is successful.

MongoDB Server is Up and running

In the above image, it can be seen that I am successfully able to connect with the mongo db. Now I will create the database named “Account-System”. While doing that, mongodb compass will ask to provide the name of our first collection, which in this case I will set as “chart-of-account”. If you are new to MongoDB, collection can be mapped with the Table from SQL. The screenshot is given below:-

Create Database

Once providing the details in the Create Database popup screen, click on the Create Database and it will create a database with chart-of-accounts collection in it as shown in the below image:-

Database Created

Configure Node Application to connect with this Database

We need to follow some certain setps in order to connect our node application with the database. For that purpose, I will add required packages into my application.

Install Required Packages

At this point in time, the only package, which I need to install in my application is mongoose.

npm install mongoos

Connect with the database

As I have installed the desired package, which is needed to connect with the database, now is the time to use it in application to connect with the database.

Just like any other package, I need to import it in my application. Once it is imported, I will be using its provided method to connect with the database. Step by step code is given below along with the description

 //File app.js
 import { mongoose } from 'mongoose';
 //#region Connect with MongoDB
mongoose.connect("mongodb://localhost:27017/Accounts-System", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});

In the above code, I have imported the mongoose and then use the connect method which is provided by mongoose to connect with the database. These lines are sufficient to connect with the database. I also added below code which is not compulsory but its useful, if you have it.

const db = mongoose.connection;
db.on('error', console.error.bind(console, "Error occured while connecting with the database"))
db.once("open", function(){
    console.log("Succesfully connected with the Mongoose Db")
});

Event Emitter and Listening an Event

In the above code, I have declared a variable named db and assigned it the property connection provided by the mongoose.

This property represent a connection with the database and it emit events whenever something happened with the connection such as when connection is

  • Open
  • Closed
  • Connecting
  • etc
In the code, I have shown my interest in the event whenever an error is occured. Behind the scene when an error is occured, mongoose raised an event named “error”, and in order to capture that event I need to listen it. The syntax to listen an event in Node.js is to use the [eventemmitter].on(“event in which you are interested”, action which you want to perform). I am doing the same thing in the last code snippet at line number 2.
So, line # 2 says, that we want to listen the error whenever mongoose.connection raised an error event.
In the same way, at line # 3, I have shown my interest to listren for the event “open”, which will be raised by mongoose.connection whenever a connection is opened. But in order to listen for this event, I used “Once” instead of using “on”. Although both are designed to register event listener, the later one is used to invoke the listener action only once, while the first one is invoked whenever its specified event is raised.

Create Model for chart of accounts

In my previouse, I did not created any model, as I was dealing with dummy and inline data which represent a person. Now is the time to write a model and its schema for our collection “Chart of Accounts”. In order to do that, add a file named “chartOfAccounts.model.js” inside the model folder and paste the following code in it:-

//File chartOfAccounts.model.js
import { mongoose } from 'mongoose';

const chartOfAccountsSchema = new mongoose.Schema({
    Code:{type: String, required: true},
    name:{type: String, required: true},
    type:{type: String, required: true,
    enum['Asset','Revenue','Liability','Expense','Equity']},
});

export const chartOfAccounts = mongoose.model("ChartsOfAccounts", chartOfAccountsSchema);

Controller for Chart of Accounts

I’ve designed the schema for the chart of accounts and based on it I have created a model for the Chart of Accounts. Now is the time to pay our attention to the controller which is responsible to interact with the database. For this purpose, I will delete my person.controller.js and will create a new controller named “chartOfAccount.controller.js”. If you are following along, you can create your new controller and keep the person.controller.js as is. However, I am deleting it to make code neat and clean. The entire code of the chartOfAccounts.controller.js is given below:-

import { chartOfAccounts } from "../models/chartOfAccounts.model.js";
// Method to fetch all records [Documents] from the Chart-Of-Accounts Table [Collection]
const getAll = async (req, res) => {
    const chartsOfAccounts = await chartOfAccounts.find();
    res.json(chartsOfAccounts);
};
//Method to get a chart of account record [Document] from the Chart-Of-Accounts Table [Collection]
const getChartOfAccountsById = async (req, res) => {
    const chartOfAccountId = req.params.id;
    const account = await chartOfAccounts.findById(chartOfAccountId);
    if(!account)
    {
        return res.status(404).json({message: 'Account not exists!'})
    }
    res.json(account);
};
// Method to create a new Chart Of Accounts record [Document] into the Chart-Of-Accounts Table [Collection]
const createChartOfAccount = async (req, res) => {
    const {code, name, type, } = req.body;
    const newAccount = await chartOfAccounts.create({
        code,name,type
    });
    res.status(201).json(newAccount);
};
// Method to update a Chart Of Accounts record [Document] into the Chart-Of-Accounts Table [Collection]
const updateChartOfAccount = async (req, res) => {
    console.log(req.body);
    const chartOfAccountId = req.params.id;
    const {code, name, type, } = req.body;
    console.log(`Record to update against Id is ${chartOfAccountId}`);
    const updatedChartOfAccount = await chartOfAccounts.findByIdAndUpdate(
        chartOfAccountId,
        {
            code,name,type
        },
        {
            new:true
        }
    );
    if(!updatedChartOfAccount)
    {
        return res.status(404).json({message: 'Account not exists!'})
    }
    return res.status(200).json(updatedChartOfAccount);
};
// Method to delete a chart of Account record [Document] from the Chart-Of-Accounts Table [Collection]
const deleteCharOfAccount = async(req,res) =>{
    const {chartOfAccountId} = req.params;
    const deletedChartOfAccount = await chartsOfAccounts.findByIdAndDelete(chartOfAccountId);
    if (!deletedChartOfAccount) {
      return res.status(404).json({ message: 'Account not found' });
    }
    res.status(200).json({ message: 'Account deleted successfully' });
};

// Export the methods
export { getAll, getChartOfAccountsById, createChartOfAccount, updateChartOfAccount,deleteCharOfAccount};
  

Description of the Controller

The above controller is almost identical to the controller which I have written in my previous controller (i.e. person.controller.js). The only difference is that now instead of using the in memory data or hard coded data, I imported the model which I have written for the Chart of Accounts.

Then I used the different method provided by the mongoose to interact with the database. e.g.

  • *.findById,
  • *.find,
  • *.create,
  • *.findByIdAndUpdate
  • etc

Note:- It is always a good practice to consult the official documentation of any package to see the available methods.

 

Router's Code for Chart of Accounts

import express from 'express';
import { getAll, getChartOfAccountsById, createChartOfAccount, updateChartOfAccount,deleteCharOfAccount } from '../controllers/chartOfAccounts.controller.js';
const Accountsrouter = express.Router();
// Middleware to parse JSON data in the request body
Accountsrouter.use(express.json());
// Define Get For Chart of Accounts. This router will co-ordinate with the controller 
Accountsrouter.get('/',getAll);
// This is also a get method. It accepts the id and return chart of account based on id 
Accountsrouter.get('/:id', getChartOfAccountsById)
// Define Post For Charts of Accounts. This router will co-ordinate with the controller to create a new record in Chart of Accounts
Accountsrouter.post('/', createChartOfAccount);
// Define Put For Chart of Accounts. This router will co-ordinate with the controller to update an existing record in Chart of Accounts
Accountsrouter.put('/:id', updateChartOfAccount);
//Define the delete endpoint to delete a record from chart of Accounts
Accountsrouter.delete('/:id',deleteCharOfAccount);
export default Accountsrouter;

Updated Main Application Code i.e. app.js

import express from 'express'
import dotenv from "dotenv"
import { mongoose } from 'mongoose';

// Import the Charts of Accounts router
import Accountsrouter from './routers/chartOfAccounts.routers.js';

dotenv.config() // this will read the file and will place the values in the process.env
const port = process.env.PORT
//just for information
console.log("Port:" + port)
//#region  Define a custom middleware
const demoMiddleware = (req,res,next)=>{
    console.log(`${req.method} ${req.url}`);
    next();
}
//#endregion

//#region Connect with MongoDB
mongoose.connect("mongodb://localhost:27017/Account-System", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, "Error occured while connecting with the database"))
db.once("open", function(){
    console.log("Succesfully connected with the Mongoose Db")
});
//#endregion


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

// Mount the custom route
app.use('/accounts/', Accountsrouter);
app.listen(port,()=>{
    console.log(`Server is listening on Port: ${port}`)
})

Final Output

In the following, I am showing the output of all the endpoints.

Create Chart of Account

Created Record in the Charts of Accounts

Update Chart of Accounts

Updated an existing record

Get All records

Get All Records

Get Chart of Account record by ID

Get Record By id

Source Code

You can find the source code of this post on the following GitHub URL:-

https://github.com/shahidriaz/https—github.com-shahidriaz-nodeexpressserver

Leave a Reply