4. MongoDB and mongoose

Ayush RajputAyush Rajput
4 min read
  1. MongoDB – The Database

    MongoDB is a NoSql Database that stores data in the form of documents and in these documents the data is written in KEY - Value pairs .

    Unlike SQL databases (tables, rows, columns), MongoDB uses:

    • Database → container of collections

    • Collection → container of documents (like a table)

    • Document → actual data stored as JSON-like objects

        {
          "_id": "64ef9fabc123", // unique key
          "name": "Ayush",
          "age": 22,
          "skills": ["Node.js", "React", "MongoDB"]
        }
      
  1. Mongoose - ODM(Object data modelling)

    Mongoose is a Node.js library that provides a schema-based solution for MongoDB.

    Think of it as a bridge between your Node.js code and MongoDB.

Mongoose WorkFlow

  1. Connect To MongoDB

     const mongoose = require('mongoose');
     require('dotenv').config();
     const dbConnect = ()=>{
         mongoose.connect(process.env.DATABASE_URL)
         .then(()=>{console.log("DB CONNECTION SUCESSFULL")})
         .catch((err)=>{
             console.log("Failed to connect DB")
             console.log(err);
             process.exit(1);
         })
     }
     module.exports = dbConnect;
    
  2. Define Schema

     const userSchema = new mongoose.Schema({
       name: { type: String, required: true },
       age: Number,
       skills: [String],
       createdAt: { type: Date, default: Date.now }
     });
    
  3. Create Model

     const User = mongoose.model('User', userSchema);// "Users" will be the collection in DB
    
  4. CRUD operations

    1. Create(POST Data)

       // Assuming Schema + Model already defined
         const User = mongoose.model("User", userSchema); 
        // ---------------- CREATE ----------------
         // Save a new user
         const newUser =  await User.create({
            name:"Ayush",
            age:5,
            skills:["java","Py"]
          })
         // Saves into DB also use save method
      
    2. Read(GET Data)

         // ---------------- READ ----------------
         // 1. find()
         const allUsers = await User.find({}); 
         // ✅ Returns an array of all the documents(USers)
         // Use when you expect multiple documents
         const getUsersWhoseAgeisFive = await User.find({age:5}) // if we use findOne here then it give first matching document
         const getSelectedFields = await User.find().select('name email -_id') // it give all documenst having only name and email and not include _id
         const getLimitedUser = await User.find().limit(5).skip(1) // this give only 5 Users exxcept first user -> used for pagination
         const sortedUser = await User.find().sort({age:1}) // return/find user in acseding order of thier age . if you pass -1 then you get the user in decending order
      
         // 2. findOne()
         const oneUser = await User.findOne({ name: "Ayush" }); 
         // ✅ Returns the first matching document (or null if none) 
         // Use when you need just ONE document
      
         // 3. findById()
         const userById = await User.findById(newUser._id); //newUser._id
         // ✅ Finds a document by _id directly
         // Faster than findOne({ _id: ... })
      
         // 4. findByIdAndUpdate()
         const updatedUser = await User.findByIdAndUpdate(
           newUser._id,
           { $set: { age: 23 } },
           { new: true } // return the updated document instead of old one
         );
         // ✅ Finds document by _id and updates it in one step
      
         // 5. findByIdAndDelete()
         await User.findByIdAndDelete(newUser._id);
         // ✅ Deletes document directly using _id
      
         // 6. findByIdAndRemove()
         await User.findByIdAndRemove("64ef9fabc123");
         // ❌ Deprecated (use findByIdAndDelete instead)
      
    3. Update

        // ---------------- UPDATE ----------------
         // 7. updateOne()
         await User.updateOne({ name: "Ayush" }, { $set: { age: 25 } });
         // ✅ Updates the FIRST matching document
      
         // 8. updateMany()
         await User.updateMany({ age: { $lt: 18 } }, { $set: { isMinor: true } });
         // ✅ Updates ALL matching documents
      
         // 9. replaceOne()
         await User.replaceOne({ name: "Ayush" }, { name: "Raj", age: 30 });
         // ✅ Replaces entire document (removes old fields not mentioned)
      
    4. Delete

         // 10. deleteOne()
         await User.deleteOne({ name: "Ayush" });
         // ✅ Deletes the first matching document
      
         // 11. deleteMany()
         await User.deleteMany({ age: { $gt: 60 } });
         // ✅ Deletes all matching documents
      
    5. Other queries

       // ---------------- EXTRA QUERY HELPERS ----------------
         // 12. countDocuments()
         const count = await User.countDocuments({ age: { $gte: 18 } });
         // ✅ Count matching documents (faster than .find().length)
      
         // 13. distinct()
         const uniqueSkills = await User.distinct("skills");
         // ✅ Returns unique values for a given field
      
         // 14. exists()
         const exists = await User.exists({ name: "Ayush" });
         // ✅ Returns _id if document exists, null if not
      
         // 15. sort()
         const sorted = await User.find().sort({ age: -1 }); 
         // ✅ Sort results (1 = asc, -1 = desc)
      
         // 16. limit()
         const limited = await User.find().limit(5);
         // ✅ Limit number of documents returned
      
         // 17. skip()
         const skipped = await User.find().skip(5).limit(5);
         // ✅ Pagination (skip first 5, then get next 5)
      
         // 18. select()
         const selectedFields = await User.find().select("name age");
         // ✅ Return only specific fields (projection)
      
         // 19. aggregate()
         const aggregation = await User.aggregate([
           { $match: { age: { $gte: 18 } } },
           { $group: { _id: null, avgAge: { $avg: "$age" } } }
         ]);
         // ✅ Powerful data aggregation pipeline
      
         // 20. populate()
         // Example: if a post has author ref
         const posts = await Post.find().populate("author");
         // ✅ Fetches related document (like JOIN in SQL)
       })();
      
  1. Advance mongoose features

    • Middleware/Hooks → run before/after operations (pre, post).

    • Virtuals → computed fields not stored in DB.

    • Population → like SQL joins (ref another model).

    • Indexes → schema-level indexing for performance.

    • Transactions → multi-document atomic operations.

        const postSchema = new mongoose.Schema({
          title: String,
          author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
        });
        const Post = mongoose.model('Post', postSchema);
      
        const post = await Post.find().populate('author');
      
0
Subscribe to my newsletter

Read articles from Ayush Rajput directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ayush Rajput
Ayush Rajput