CRUD Operation in Node js and MongoDB

The CRUD operations are four basic data handling operations where user can create, read(retrieve), update and delete. These are related to both requests of client-side and operation performed in the backend to handle the requests of clients.

What is CRUD?

CURD is the basic database operation which is used to manipulate data and modify it with the user’s need and time.

  1. Create (post) – Insert data
  2. Read(Get) – Retrive data
  3. Update(put) – Change in current data
  4. Delete(delete) – Destroy the data

The operations are performed after certain requests are made by the client, As the client sends the HTTP requests then we can set the backend operations according to that request. All the Request carry different meanings and task to carried out, As per the HTTP requests of the client we use the different functions that are associated with CRUD operations to execute the task.

Task     Function In MongoDB HTTP Requests
Create .create() POST
read .find() GET
Update .update() PUT
Delete .remove() DELETE

Note:- Get and Post requests are easily handled in node js but the put and delete are managed by the method-override library.

Initialize the Project First

PS D:\work\Codebun\CURD>npm init

Product Schema for CRUD

  • Create a root directory and inside it create a folder named as models.
  • Inside models folder create a product.js file which will contain schema for the product.
  • Install Mongoose Using the Command.
    PS D:\work\Codebun\CURD>npm install mongoose
  • Require Mongoose and create the schema for a product, pass the properties like name of the product as a string, image as string and price as number and export.
    const mongoose = require("mongoose");
    
    var productSchema = new mongoose.Schema({
        name:String,
        image:String,
        price:Number
    })
    
    module.exports = mongoose.model("Product",productSchema);

    This Creates the basic Entity of the data we are gonna perform CRUD operations on.

What is Method-Override?

It is a node package which is used to rewrite the PUT and DELETE requests on top of other HTTP requests made by the client. Use the command to install method

PS D:\work\Codebun\CURD>npm i method-override

We can use the query string to override the method, we have to make sure that in app.js it has been given an extension to be used. This method of using query value is used with HTML <form>  where we send requests as a post requests.

Sending Requests through client-side.

  • Create a views directory and inside that create a file named as index.ejs.
  • Create a boilerplate code for HTML and add a form to send a POST request to insert the data inside the database.
  • Below that create the table to retrieve the data and display.
  • Create two buttons for the edit routes and delete route.
  • Install the method-override package and use in the form to rewrite POST request to put and delete.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CURD Operation</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
</head>
<body>
    <section class="add">
        <form action="/add" method="POST">
            <label for="name">Name</label>
            <input type="text" id="name" name="name" placeholder="productName">
            <label for="image">Image</label>
            <input type="text" id="image" name="image" placeholder="Image-URL">
            <label for="price">Price</label>
            <input type="number" id="price" name="price" placeholder="productPrice">
            <input type="submit">
        </form>
    </section>
    <br>
    <br>
    <hr>
    <section class="show">
        <table class="table">
            <tr>
            <th>Name</th>
            <th>image`</th>
            <th>price</th>
        </tr>
        <% products.forEach(function(product){ %>
            <tr> <td> <h4><%= product.name %></h4> </td>    
            <td><img src="<%= product.image %>" alt="" style="width: 100px;height: 100px;"> </td>
            <td><h5><%=product.price%></h5></td>
            <td><a class="btn btn-warning" href="/<%=product._id%>/edit">EDIT </a></td>
            <td><form action="/<%=product._id%>/?_method=DELETE" method="POST"><button class="btn btn-danger">Delete</button></form></td>
            </tr>
        <% }) %>
    </table>
    </section>
    
</body>
</html>
  • In views create an ejs file foe edit form,
  • Retrieve all the information of that product there in the form of values.
  • Make an edit and a button to submit changes.
  • And a link to go back to Home Page
<h1>Edit <%=product.name%></h1>
<form action="/<%=product._id%>/edit?_method=PUT" method="POST">
        <label for="name">Name</label>
        <input type="text" id="name" name="product[name]" value="<%=product.name%>">
        <label for="image">Image</label>
        <input type="text" id="image" name="product[image]" value="<%=product.image%>">
        <label for="price">Price</label>
        <input type="number" id="price" name="product[price]" value="<%=product.price%>">
        <input type="submit">
</form>
<a href="/">GOBACK-></a>

Configure App.js

  • Install all the Libraries and dependencies using “npm install”.
    • Libraries:-  ejs,body-parser,express,mongoose,method-override.
  • Setup the express and create a server on a localhost port.
  • Connect to the MongoDB database and pass its parameter. (Read the tutorial for MongoDB connectivity)
  • Set the ejs engine and use body-parser and method-override to be used in view files.
const express = require("express"),
        app = express(),
        bodyParser = require("body-parser"),
        Product = require("./models/product"),
        methodOverride = require("method-override");
        mongoose = require("mongoose");

mongoose.connect("mongodb://localhost/CURD10",{
    useNewUrlParser:true,
    useUnifiedTopology:true,
    useCreateIndex:true
});
app.set("view engine","ejs");
app.use(bodyParser.urlencoded({ extended:true }));
app.use(methodOverride("_method"));

//Routes and logic will go here

app.listen(2000,(err)=>{
    if(err){
        console.log(err);
    }else {
        console.log("Server Started At PORT 2000");
    }
})

Routes and Logic For CRUD

1. Create

  • To add product we use post route and route name “/add”.
  • Pass the data from the body using to body-parser to the particular variables.
  • Make an object variable named as newProduct the contains all information from the form that is collected in temporary variables.
  • In the callback function, we use  schemaName.create() function pass the newProduct object variable and callback as parameters.
  • If an error occurs console.log() the error and if success than redirect to the home page.
    //add Product
    app.post("/add",(req,res)=>{
        var name = req.body.name;
        var image = req.body.image;
        var price = req.body.price;
        var newProduct = {name:name,image:image,price:price};
        Product.create(newProduct,(err,data)=>{
            if(err){
                console.log(err);
            }else {
                console.log(data);
                res.redirect("/");
            }
        })
    })

2. Read

  • Use get a request to render the home page
  • Use the imported SchemaName.find() function in callback.
  • This will find all product in the base and will be passed to the rendered page if there is no error.
//Show product and homepage
app.get("/",(req, res)=>{
    Product.find({},(err,products)=>{
        if (err) {console.log(err);
        }else{
            res.render("index",{products: products});
        }
    })
    
})

3. Update

  • Here we Use a get route to find the particular product and the put route to update the changes.
  • As every Object stored in MongoDB have a unique id we use that id find that object.
  • Then to make changes we use put route and a mongoose function findByIdAndUpdate() to update the pre-existing information of product and redirect to the home page.
//Get EditForm
app.get("/:id/edit",(req,res)=>{
    Product.findById(req.params.id,function (err, product){
        if(err){
            console.log(err);
            res.redirect("/");
        }else{
            res.render("edit",{product: product});
        }
    })
})

//Edit Put request
app.put("/:id/edit",(req, res)=>{
    Product.findByIdAndUpdate(req.params.id,req.body.product,function(err,updatedata){
        if(err){
            console.log(err);
            res.redirect("/");
        }else{
            res.redirect("/");
        }
    })
})

4. Delete

  • We use delete request passing the route and a callback functions
  • Then use the schemaName.findByIdAndRemove() passing id and a callback
  • if an error occurs then we will console the error and redirect to home page
  • And if an error doesn’t occur then we will be redirected to the home page only. But this time the product will be deleted
//Delete the product
app.delete("/:id",(req,res)=>{
    Product.findByIdAndRemove(req.params.id,function (err){
        if(err){
            console.log(err);
            res.redirect("/");
        }else {
            res.redirect("/");
            }
    })
})

Output:-

HomePage

 

Edit Form

App.js File:-

const express = require("express"),
        app = express(),
        bodyParser = require("body-parser"),
        Product = require("./models/product"),
        methodOverride = require("method-override");
        mongoose = require("mongoose");

mongoose.connect("mongodb://localhost/CURD10",{
    useNewUrlParser:true,
    useUnifiedTopology:true,
    useCreateIndex:true
});
app.set("view engine","ejs");
app.use(bodyParser.urlencoded({ extended:true }));
app.use(methodOverride("_method"));

//Show product and homepage
app.get("/",(req, res)=>{
    Product.find({},(err,products)=>{
        if (err) {console.log(err);
        }else{
            res.render("index",{products: products});
        }
    })
    
})
//add Product
app.post("/add",(req,res)=>{
    var name = req.body.name;
    var image = req.body.image;
    var price = req.body.price;
    var newProduct = {name:name,image:image,price:price};
    Product.create(newProduct,(err,data)=>{
        if(err){
            console.log(err);
        }else {
            console.log(data);
            res.redirect("/");
        }
    })
})

//Get EditForm
app.get("/:id/edit",(req,res)=>{
    Product.findById(req.params.id,function (err, product){
        if(err){
            console.log(err);
            res.redirect("/");
        }else{
            res.render("edit",{product: product});
        }
    })
})

//Edit Put request
app.put("/:id/edit",(req, res)=>{
    Product.findByIdAndUpdate(req.params.id,req.body.product,function(err,updatedata){
        if(err){
            console.log(err);
            res.redirect("/");
        }else{
            res.redirect("/");
        }
    })
})

//Delete the product
app.delete("/:id",(req,res)=>{
    Product.findByIdAndRemove(req.params.id,function (err){
        if(err){
            console.log(err);
            res.redirect("/");
        }else {
            res.redirect("/");
            }
    })
})



app.listen(2000,(err)=>{
    if(err){
        console.log(err);
    }else {
        console.log("Server Started At PORT 2000");
    }
})