Kazi Rahamatullah
Kazi Rahamatullah
AboutProjectsBlogContact
UsesBooks
ResumeView CV
Kazi Rahamatullah

© Copyright 2026 Kazi Rahamatullah

AboutProjectsBlogBooksUses
Twitter/XGitHubProduct HuntCodeSandbox
Back to Blog
MERNMongoDBMongooseNoSQLDatabaseBackend

MERN Course: MongoDB Essentials

Weeks 17–18 of the MERN syllabus — NoSQL concepts, Mongoose schemas, CRUD, relationships, aggregation, indexing, and query performance.

Jul 10, 20265 min read

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

#TopicDescription
1Introduction to NoSQL and MongoDBMongoDB stores documents (BSON/JSON-like) in collections.
2Mongoose Schema DesignMongoose defines schemas, types, validation, and middleware.
3CRUD Operations with MongooseAll Mongoose operations return Promises — use async/await.
4Advanced Querying TechniquesCombine $gt, $in, $or filters with sort, skip/limit pagination.
5Relationships: Embed vs ReferenceEmbed related data when read together and bounded in size (comments on a post).
6Aggregation, Indexes & Best PracticesAggregation 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:

javascript
// MongoDB shell
use merndb
db.posts.insertOne({
  title: 'MERN Course',
  tags: ['mongodb', 'mern'],
  publishedAt: new Date(),
})

Note

MongoDB is not "schemaless" — enforce shape in application layer (Mongoose) or JSON Schema validators.

Tip

Apply this in your Week 17 course project before moving on.

Performance

Design queries first, then schema. Index fields you filter and sort on — unindexed collection scans do not scale.

Back to index


2. Mongoose Schema Design

Mongoose defines schemas, types, validation, and middleware. Models map to collections.

Example:

javascript
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)

Note

Use mongoose.models.X ?? mongoose.model() in Next.js to avoid OverwriteModelError on hot reload.

Tip

Apply this in your Week 17 course project before moving on.

Performance

Add compound indexes for common query patterns: { tags: 1, publishedAt: -1 }.

Back to index


3. CRUD Operations with Mongoose

All Mongoose operations return Promises — use async/await. Handle validation errors (ValidationError) separately from server errors.

Example:

javascript
// 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)

Note

Use .lean() for read-only API responses — returns plain objects, faster and less memory than Mongoose documents.

Tip

Apply this in your Week 17 course project before moving on.

Performance

Select only needed fields: .select("title slug createdAt") — reduces wire size and parsing cost.

Back to index

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:

javascript
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()

Note

Offset pagination (skip) slows down on deep pages. Use { _id: { $lt: lastId } } cursor pagination instead.

Tip

Apply this in your Week 18 course project before moving on.

Performance

Create text indexes for search: postSchema.index({ title: "text", content: "text" }).

Back to index


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:

javascript
// 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] })

Note

Embedding duplicates data. Updating embedded copies across documents is painful — reference + populate when data is shared.

Tip

Apply this in your Week 18 course project before moving on.

Performance

Limit populate depth. N+1 populate calls kill API latency — use aggregation $lookup for batch joins.

Back to index


6. Aggregation, Indexes & Best Practices

Aggregation pipelines $match, $group, $sort power analytics. Indexes are mandatory at scale.

Example:

javascript
const stats = await Post.aggregate([
  { $match: { publishedAt: { $gte: startDate } } },
  { $unwind: '$tags' },
  { $group: { _id: '$tags', count: { $sum: 1 } } },
  { $sort: { count: -1 } },
  { $limit: 10 },
])

Note

Run explain("executionStats") on slow queries in MongoDB Compass or shell — look for COLLSCAN.

Tip

Apply this in your Week 18 course project before moving on.

Performance

Keep working set in RAM. Monitor index size; drop unused indexes — they slow writes.

Back to index


Share this article

XLinkedInFacebook
Kazi Rahamatullah

Written by

Kazi Rahamatullah

FullStack Developer

X / TwitterGitHubLinkedIn

Subscribe to my newsletter

Stay up to date and get notified when I share new contents.

No spam ever, unsubscribe anytime