Next.js 13, Explore Mongodb And Mongoose. Crud Operations - Post/Get/Patch

  • Posted on October 21, 2023
  • Technology
  • By MmantraTech
  • 203 Views

Hey guys In this article I will explain you about Mongoose tool for MongoDB Database. But before going to delve into it I would like to pay your attention some important points about 

Prerequisite

  • Basic understanding with MongoDb.
  • React/Next Js



Don't be confused for below terms.

  • Mongodb
  • Mongoose

 

Thumnail-Python-If-Else (24)-SLR2u7xMsH.png

MongoDB is the native driver for interacting with a mongodb instance which stores data in the form of BSON documents

MongoDB, a leading NoSQL database, revolutionizes the way data is stored and managed. Unlike traditional relational databases, MongoDB adopts a document-oriented approach, storing data in flexible JSON-like documents. This schema-free nature allows developers to work with evolving data structures seamlessly, eliminating the constraints of predefined schemas prevalent in relational databases.

What is Mongoose ?

It can be considered as a middleware between MongdoDB Drivers and Node.js Application so that strong communication can be established.  It is an Object modelling tool for Mongodb.

According to offical site :

Mongoose is a Node.js-based Object Data Modeling (ODM) library for MongoDB. It is akin to an Object Relational Mapper (ORM) such as SQLAlchemy for traditional SQL databases. The problem that Mongoose aims to solve is allowing developers to enforce a specific schema at the application layer. In addition to enforcing a schema, Mongoose also offers a variety of hooks, model validation, and other features aimed at making it easier to work with MongoDB.

It allows users to define Database models using Database Schema and provides lot of features like validations, plugins to work with MongoDB. In other words we can say, MongoDB and Mongoose provide a Database Managment functinalities in modern web applications.

Key Features of MongoDB

1. Schema Flexibility
MongoDB's schema flexibility enables the storage of diverse data types within the same collection. Fields within documents can vary, providing the freedom to accommodate changing data models without complex migrations.

2. High Performance:
MongoDB excels in delivering high-performance read and write operations. Its architecture is designed for horizontal scalability, ensuring seamless handling of data growth. Automatic sharding distributes data across multiple nodes, maintaining high availability and responsiveness.

 3. JSON-Like Documents:
Data in MongoDB is stored in BSON (Binary JSON) format, supporting a wide range of data types, including nested arrays and documents. This JSON-like structure simplifies the process of mapping application objects to database entities, enhancing development efficiency.

4. Indexing:
MongoDB’s support for secondary indexes enhances query performance. Indexes enable efficient searching, sorting, and filtering of data, ensuring rapid retrieval of information from large datasets.

 

 CRUD Operations in MongoDB using Mongoose

 

Let’s explore the fundamental CRUD operations in MongoDB with NEXT.js 13

I am assuming you already know about Next.js 13 and its installation. However for quick recap you check below my previouse articles and youtube vides links:

Article links :

https://mmantratech.com/what-are-props-in-react-js-next-js-should-i-follow-or-avoid-props-drilling

https://mmantratech.com/what-are-route-handlers-and-api-routes-in-nextjs-what-changed-after-next-js-v13-2-node-environment-inbuild-with-nextjs

https://mmantratech.com/how-to-install-use-redux-store-in-react-next-js-app-using-reactjs-toolkit-let-s-do-practical

https://mmantratech.com/what-is-react-redux-state-management-a-deep-understanding-with-react-redux-best-practices

Video Links :

https://youtu.be/ixh79z5iH14

https://youtu.be/qVjTJwPeFrw

https://youtu.be/pDLa2Cm6jdk

https://youtu.be/Ym6Xg-Z_xys

 

Create Next.js App

npx ceate-next-app@latest

I will follow below files and folder structure for this tutorial:

 

STEP 1 :

Create a file ".env.local" at root of the project . put below code.

MONGO_URI=mongodb://127.0.0.1:27017/crm

Create a folder "app/config" and create a file "database.js" in config folder. Put below code in database.js file. 

import mongoose from "mongoose";

const MONGO_DB = process.env.MONGO_URI;
console.log(MONGO_DB);
if (!MONGO_DB) {
  throw new Error("Invalid Datbase URL");
}
async function dbConnect() {
  const opts = {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  };


 mongoose.connect(MONGO_DB, opts);
  const db = mongoose.connection;

  db.on("error",console.error.bind("console","connection.error:"))
  db.once("open",function(){
  console.log("Database Connected successfully")
  })
  // const cc = mongoose.connect(MONGO_DB, opts).then((mongoose) => {
  //   console.log("====================================");
  //   console.log("You have successfully Connected");
  //   console.log("====================================");
  //   return mongoose;
  // });

  return db;
}

export default dbConnect;

The above code makes MongoDB connection that can be use anywhere in the project 

STEP 2 :

Create a folder "app/models" and create a file "Employee.js" in config folder. Put below code in Employee.js file.

import mongoose from "mongoose";
const employeeSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  basic_salary: {
    type: String,
    required: true,
  },
  mobile: {
    type: String,
    required: true,
  },
});

module.exports = mongoose.models.Employee || mongoose.model("Employee",employeeSchema);

The above is for creating Employee Schema Model and this model will be used to interact with Mongodb Database

Let's create API Route Handlers for CRUD operatons in Mongoose

STEP 3 :

Create a folder "app/api" and it should be like below screen.

 

API Routes : 

GET : api/employee/

POST : api/employee/

PATCH : update/delete [ api/employee/id ]

 

STEP 4 :

Create a folder "app\api\employee" and create a file "route.js" inside employee folder. Put below code in the file "route.js"

import { NextRequest, NextResponse } from "next/server";
import dbConnect from "@/app/config/database";
dbConnect();
import Employee from "@/app/models/Employee";

export async function GET(req,res)
{
  console.log(req)
   const employees = await Employee.find({}); //return all records  
  return NextResponse.json({ msg: employees });
}

 

GET : http://localhost:3000/api/employee/

Let's understand how to fetch all records from the database. If I relate this to Mysql then surely it will be like "select * from employee".

=> Fetch all records : find({})

In Mongodb using mongoose you need find({}) method. If you leave blank object it will fetch all records from the table.

=> Fetch a record by ID : findById(id)

In Mongodb using mongoose you need findById(id) method. you have to pass object ID as a argument and it will fetch the record. Consider below code for better understanding 

import { NextRequest, NextResponse } from "next/server";
import dbConnect from "@/app/config/database";
dbConnect();
import Employee from "@/app/models/Employee";
import mongoose from "mongoose";

export async function GET(req) 
{

  const { searchParams } = new URL(req.url);
  const id = searchParams.get("id");

  console.log("id>>", id);

  if (mongoose.Types.ObjectId.isValid(id)) 
  {
    const employees = await Employee.findById(id); //return all records
    return NextResponse.json({ msg: employees });
  }

  return NextResponse.json({ msg: "Invalid Object ID" });

}

 

In the above code in order to check that Object Id is valid MongoDB id or not we have use isValid() method to be sured.

 

=> Fetch a record by any field : findOne({name:"kamal})

In Mongodb using mongoose you need findOne({name:"kamal}) method. you have to pass name as a argument and it will fetch the record. Consider below code for better understanding 

//---------------------Fetch Record by any field
export async function GET(req) 
{
  const { searchParams } = new URL(req.url);
  const name = searchParams.get("name");
    console.log(name);  

  const user = await Employee.findOne({ name: name });
  return NextResponse.json({ msg: user });
}

 

----------- INSERT RECORD -----------------

 

=> Employee.create({ name, mobile, basic_salary });

export async function POST(req, res) {
  try {
    const body = await req.json();

    const name = body.name;
    const mobile = body.mobile;
    const basic_salary = body.salary;

    const user = await Employee.create({ name, mobile, basic_salary });
    return NextResponse.json({ msg: user });
  } catch (error) {

    return NextResponse.json({ msg: error.message });

  }
}

 

Another way to insert record :

 

export async function POST(req, res) {
  try {
    const body = await req.json();

    const name = body.name;
    const mobile = body.mobile;
    const basic_salary = body.salary;

    // const user = await Employee.create({ name, mobile, basic_salary });
     const user = new Employee();
     user.name= name;
     user.mobile=mobile;
     user.basic_salary=basic_salary;
     user.save();


    return NextResponse.json({ msg: user });
  } catch (error) {

    return NextResponse.json({ msg: error.message });

  }
}

 

In this method you can create object of Model class and set properties one by one

---------Dynamic Routes : Update/Delete Model ---------

I hope you must have worked over dynamic Routes in next.js . Don't worry if you don't know I will give you quick recap for this. Dynamic routes in next.js is to provide a parameter which will change its value during execution. For ex. product ID, User Id , etc. To handle Dynamic routes you folder structure should be as follows:

As you can see I have made a folder which is surrouned by square brackets. Square brackets tells the next.js that this variable value , in my case "id", will change its value. So you need to create a folder "app/api/[id]" . you must remember the name in square brackets is a parameter and it should be considered as per your situation.

Let's do some update operations:

In this folder [id], create a file "route.js" and put below code :

import { NextResponse } from "next/server";
import dbConnect from "@/app/config/database";
import Employee from "@/app/models/Employee";
import mongoose from "mongoose";

export async function PATCH(req, { params }) {
  try {
    const id = params.id;
    console.log(id);
    const body = await req.json();

    const name = body.name;
    const mobile = body.mobile;
    const basic_salary = body.salary;

    if (!mongoose.Types.ObjectId.isValid(id)) {
      return NextResponse.json({ msg: "Invalid  ID" });
    }

    await dbConnect();

    // const user = await Employee.find({})
    const filter =  id ;
    console.log(id)
    const data = {
      name: name,
      basic_salary: basic_salary,
      mobile: mobile,
    };

    const user = await Employee.findByIdAndUpdate(filter, data );

    return NextResponse.json({ msg: user });
  } catch (error) {
    return NextResponse.json({ msg: error.message });
  }
}

 

http://localhost:3000/api/employee/652bf55a4ae96043ec141025

 

In order to access id parameters from the url we have used "{ params } " and received value by  "const id = params.id"

 

=> Employee.findByIdAndUpdate(id,{ name, mobile, basic_salary });

What if we need to update document by any field for ex. mobile no. in this case we can use :

=> Employee.updateOne({"mobile:mobile},{ name, basic_salary });

export async function PATCH(req, { params }) {
  try {
    const id = params.id;
    console.log(id);
    const body = await req.json();

    const name = body.name;
    const mobile = body.mobile;
    const basic_salary = body.salary;

    // if (!mongoose.Types.ObjectId.isValid(id)) {
    //   return NextResponse.json({ msg: "Invalid  ID" });
    // }

    await dbConnect();

    // const user = await Employee.find({})
    const filter =  {"mobile":id} ;
    console.log(id)
    const data = {
      name: name,
      basic_salary: basic_salary,

    };

    const user = await Employee.updateOne(filter, data );

    // const user = await Employee.findByIdAndUpdate(filter, {  data });

    return NextResponse.json({ msg: user });
  } catch (error) {
    return NextResponse.json({ msg: error.message });
  }
}

Updating existing documents in MongoDB can be done using the `updateOne()` or `updateMany()` methods.

For references:

=>  Updating a single document
db.users.updateOne({ name: "Alice" }, { $set: { age: 29 } });

=>  Updating multiple documents
db.users.updateMany({ age: { $gte: 30 } }, { $inc: { age: 1 } });
```

-------------------- Delete Operation----------------------

 

=> Employee.findByIdAndDelete(id);

 

const user = await Employee.findByIdAndDelete(id);

It deletes the document and returnded deleted document

 

const user = await Employee.deleteOne({"mobile":id})

By this you can delete the document by any fields

const user = await Employee.findOneAndDelete({"mobile":id})

It deletes but also returned the Deleted Document

For references:

To remove documents from a collection, MongoDB offers the `deleteOne()` and `deleteMany()` methods.


=> Deleting a single document
db.users.deleteOne({ name: "Bob" });

=> Deleting multiple documents
db.users.deleteMany({ age: { $lt: 30 } });

By executing these CRUD operations, MongoDB using mongoose empowers developers to manage data efficiently, ensuring seamless integration and retrieval of information in real-time.

 

0
Author
No Image
Admin
MmantraTech

Mmantra Tech is a online platform that provides knowledge (in the form of blog and articles) into a wide range of subjects .

You May Also Like

Write a Response