MERN Course: MongoDB Essentials
Weeks 17–18 of the MERN syllabus — NoSQL concepts, Mongoose schemas, CRUD, relationships, aggregation, indexing, and query performance.
Introduction
MongoDB is the database in MERN. This post turns the syllabus into hands-on Mongoose patterns with indexing and pagination strategies you need for production APIs.
Course Reference
Quick index
| # | Topic | Description |
|---|---|---|
| 1 | Introduction to NoSQL and MongoDB | MongoDB stores documents (BSON/JSON-like) in collections. |
| 2 | Mongoose Schema Design | Mongoose defines schemas, types, validation, and middleware. |
| 3 | CRUD Operations with Mongoose | All Mongoose operations return Promises — use async/await. |
| 4 | Advanced Querying Techniques | Combine $gt, $in, $or filters with sort, skip/limit pagination. |
| 5 | Relationships: Embed vs Reference | Embed related data when read together and bounded in size (comments on a post). |
| 6 | Aggregation, Indexes & Best Practices | Aggregation pipelines $match, $group, $sort power analytics. |
Week 17: MongoDB Fundamentals & Mongoose
1. Introduction to NoSQL and MongoDB
MongoDB stores documents (BSON/JSON-like) in collections. Schema-flexible — great for evolving MERN apps; relational joins are less natural than SQL.
Example:
// MongoDB shell
use merndb
db.posts.insertOne({
title: 'MERN Course',
tags: ['mongodb', 'mern'],
publishedAt: new Date(),
})2. Mongoose Schema Design
Mongoose defines schemas, types, validation, and middleware. Models map to collections.
Example:
import mongoose from 'mongoose'
const postSchema = new mongoose.Schema(
{
title: { type: String, required: true, trim: true, maxlength: 200 },
slug: { type: String, required: true, unique: true, index: true },
content: { type: String, required: true },
tags: [{ type: String, trim: true }],
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
},
{ timestamps: true },
)
export const Post = mongoose.models.Post ?? mongoose.model('Post', postSchema)3. CRUD Operations with Mongoose
All Mongoose operations return Promises — use async/await. Handle validation errors (ValidationError) separately from server errors.
Example:
// Create
const post = await Post.create({ title: 'Hello', slug: 'hello', content: '...' })
// Read
const posts = await Post.find({ tags: 'mern' }).sort({ createdAt: -1 }).limit(10).lean()
// Update
await Post.findByIdAndUpdate(id, { title: 'Updated' }, { new: true, runValidators: true })
// Delete
await Post.findByIdAndDelete(id)Week 18: Advanced Queries, Relationships & Performance
4. Advanced Querying Techniques
Combine $gt, $in, $or filters with sort, skip/limit pagination. Use cursor-based pagination for large datasets.
Example:
const page = await Post.find({
publishedAt: { $gte: new Date('2026-01-01') },
tags: { $in: ['mern', 'react'] },
})
.sort({ publishedAt: -1 })
.skip((pageNum - 1) * 10)
.limit(10)
.lean()5. Relationships: Embed vs Reference
Embed related data when read together and bounded in size (comments on a post). Reference when data is shared or unbounded (user on many posts).
Example:
// Reference — populate author
const posts = await Post.find().populate('author', 'name avatar').lean()
// Embed — comments array on post (small threads only)
const commentSchema = new mongoose.Schema({
body: { type: String, required: true },
userName: String,
createdAt: { type: Date, default: Date.now },
})
// postSchema.add({ comments: [commentSchema] })6. Aggregation, Indexes & Best Practices
Aggregation pipelines $match, $group, $sort power analytics. Indexes are mandatory at scale.
Example:
const stats = await Post.aggregate([
{ $match: { publishedAt: { $gte: startDate } } },
{ $unwind: '$tags' },
{ $group: { _id: '$tags', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 10 },
])Subscribe to my newsletter
Stay up to date and get notified when I share new contents.
No spam ever, unsubscribe anytime