What is Mongoose?

Mongoose is a MongoDB object modeling library for Node.js. It provides a straightforward way to interact with MongoDB by using schemas and models

Key Features of Mongoose

  1. Schemas and Models

    Example:

    import mongoose ,{Schema} from "mongoose"
    
    const userSchema= new Schema({
        username:{
            type:String,
            required:true,
            unique:true,
            lowercase:true,
            trim:true,
            index:true
    
        },
        email:{
            type:String,
            required:true,
            unique:true,
            lowercase:true,
            trim:true
    
        }
    
    },{timestamps:true})
    
    
  2. Middleware (Hooks)

    Example:

    
    userSchema.pre('save', function(next) {
        // Perform something before saving
        console.log('Before saving...');
        next();
    });
    
    userSchema.pre("save",async function(next){
        if(!this.isModified("password")) return next();
        this.password =await bcrypt.hash(this.password,10)
        next()
    })
    
    
  3. Queries

    Example:

    
    User.find({ age: { $gte: 18 } })
    
    
  4. Relationships Between Data

    Example (One-to-many relationship):

    
    const videoSchema= new Schema(
        {
    
            owner:{
                type:Schema.Types.ObjectId,
                ref:"User"
            }
    
        },{
            timestamps:true
        }
    )
    
    
  5. Plugins

 import mongoose,{Schema} from "mongoose"
import aggregatePaginate from "mongoose-aggregate-paginate-v2"

const videoSchema= new Schema(

)

videoSchema.plugin(aggregatePaginate);
export const Video=mongoose.model("Video",videoSchema)


How aggregatePaginate Works

Normally, with MongoDB, when you use an aggregation pipeline, you might retrieve a large number of documents. However, fetching all of them at once can be inefficient or slow. Pagination helps break the results into smaller chunks, loading only a subset of the data at a time (e.g., 10 items per page).

With aggregatePaginate, you can run an aggregation query and then paginate through the results without manually managing the skip/limit logic

How Mongoose Works

  1. Connection: First, you connect to a MongoDB database.
  2. Define Schema: Define the schema that describes your data structure.
  3. Create Model: Create a model from the schema to interact with the database.
  4. Perform Operations: Use the model to perform CRUD operations (Create, Read, Update, Delete) on the database.

User Model example

**User Model**

import mongoose ,{Schema} from "mongoose"
import bcrypt from "bcrypt"
import jwt from "jsonwebtoken"

const userSchema= new Schema({
    username:{
        type:String,
        required:true,
        unique:true,
        lowercase:true,
        trim:true,
        index:true

    },
    email:{
        type:String,
        required:true,
        unique:true,
        lowercase:true,
        trim:true

    },
    fullName:{
        type:String,
        required:true,
        trim:true,
        index:true

    },
    avatar:{
        type:String,///cloudinary url
        required:true,

    },
    coverImage:{
        type:String,///cloudinary url
    },
    watchHistory:{
        type:Schema.Types.ObjectId,
        ref:"video"

    },
    password:{
        type:string,
        required:[true,"Password is reuired"]
    },
    refreshToken:{
        type:String

    }

},{timestamps:true})

///////This line registers a middleware function to be executed before the "save"
///operation on a document of the specified schema (userSchema).

//async function(next) { ... }: This is the middleware function itself,
/// which takes a callback function next as its argument.
///The next function is used to proceed to the next middleware in the stack

///////If it hasn't been modified (i.e., it's not a new password or an updated password),
/// the function exits early by calling next() to proceed to the next middleware.

userSchema.pre("save",async function(next){
    if(!this.isModified("password")) return next();
    this.password =await bcrypt.hash(this.password,10)
    next()
})

userSchema.methods.isPasswordCorrect= async function(password){
    return await bcrypt.compare(password,this.password)
}

userSchema.methods.generateAccessToken=function(){
     return jwt.sign({
        _id:this._id,
        email:this.email,
        username:this.username,
        fullName:this.fullName

    }),
    process.env.ACCESS_TOKEN_SECRET,
    {
        expiresIn:process.env.ACCESS_TOKEN_EXPIRY
    }
}
userSchema.methods.generateRefreshToken=function(){
     return jwt.sign({
        _id:this._id,
        email:this.email,
        username:this.username,
        fullName:this.fullName

    }),
    process.env.REFRESH_TOKEN_SECRET,
    {
        expiresIn:process.env.REFRESH_TOKEN_EXPIRY
    }
}

export const User=mongoose.model("User",userSchema)