Practical Lab: Build a Course Management Dataset
In this lab, build a small course catalog and practice all four CRUD categories using realistic documents.
Step 1: Create the practice dataset
use mongodb_course_lab
db.courseCatalog.insertMany([
{
_id: "course-101",
title: "MongoDB Fundamentals",
category: "database",
level: "beginner",
price: NumberDecimal("0.00"),
published: true,
tags: ["mongodb", "database", "beginner"],
instructor: {
name: "Arun",
city: "Chennai"
},
enrolledStudents: 120,
createdAt: ISODate("2026-10-01T10:00:00Z")
},
{
_id: "course-102",
title: "MongoDB Aggregation",
category: "database",
level: "intermediate",
price: NumberDecimal("499.00"),
published: true,
tags: ["mongodb", "aggregation"],
instructor: {
name: "Meera",
city: "Bengaluru"
},
enrolledStudents: 80,
createdAt: ISODate("2026-10-05T10:00:00Z")
},
{
_id: "course-103",
title: "React Essentials",
category: "frontend",
level: "beginner",
price: NumberDecimal("299.00"),
published: false,
tags: ["react", "javascript"],
instructor: {
name: "Ravi",
city: "Chennai"
},
enrolledStudents: 0,
createdAt: ISODate("2026-10-10T10:00:00Z")
}
]);
Step 2: Read operations
Find all published courses:
db.courseCatalog.find({ published: true });
Find beginner courses:
db.courseCatalog.find({ level: "beginner" });
Find courses with prices between 100 and 500:
db.courseCatalog.find({
price: {
$gte: NumberDecimal("100"),
$lte: NumberDecimal("500")
}
});
Find courses taught by instructors in Chennai:
db.courseCatalog.find({ "instructor.city": "Chennai" });
Find courses containing the mongodb tag:
db.courseCatalog.find({ tags: "mongodb" });
Return only titles and prices:
db.courseCatalog.find(
{},
{ title: 1, price: 1, _id: 0 }
);
Step 3: Update one course
db.courseCatalog.updateOne(
{ _id: "course-102" },
{
$set: {
published: false
},
$currentDate: {
updatedAt: true
}
}
);
Verify the result:
db.courseCatalog.findOne({ _id: "course-102" });
Step 4: Update several courses
db.courseCatalog.updateMany(
{ category: "database" },
{ $set: { featured: true } }
);
Inspect the affected documents and the operation result.
Step 5: Update an array
db.courseCatalog.updateOne(
{ _id: "course-101" },
{
$addToSet: {
tags: "developer"
}
}
);
Step 6: Upsert a course setting
db.courseSettings.updateOne(
{ courseId: "course-101" },
{
$set: {
theme: "dark"
},
$setOnInsert: {
createdAt: new Date()
}
},
{ upsert: true }
);
For a real application, consider a unique index on courseId if each course should have only one settings document.
Step 7: Delete a practice course
Inspect the target:
db.courseCatalog.find({ _id: "course-103" });
Delete it:
db.courseCatalog.deleteOne({ _id: "course-103" });
Step 8: Verify the final state
db.courseCatalog.find().sort({ _id: 1 });
Challenge tasks
- Insert a course with an ObjectId identifier instead of a string identifier.
- Find all courses that have either the mongodb or react tag.
- Find unpublished courses with zero enrollments.
- Update the instructor city for one course without replacing the entire instructor document.
- Increase the enrollment count of one course by 10.
- Remove a deprecated tag from every course that contains it.
- Create a unique index on a suitable course field and test duplicate insertion behavior.
- Perform an upsert using a stable course key.
- Explain the difference between matchedCount and modifiedCount.
- Explain why updateMany() is not automatically atomic across the entire collection.
- Compare updateOne() with replaceOne().
- Describe a safe workflow for deleting all unpublished test courses without affecting published courses.
Run a CRUD verification query
print("Total courses:", db.courseCatalog.countDocuments({}));
print("Published courses:");
printjson(db.courseCatalog.find({ published: true }).toArray());
print("Database courses:");
printjson(db.courseCatalog.find({ category: "database" }).toArray());
print("Course titles and levels:");
printjson(
db.courseCatalog.find(
{},
{ title: 1, level: 1, _id: 0 }
).toArray()
);💡 The verification queries count the current documents, filter published courses, select database courses, and project selected fields. In a large production collection, avoid using toArray() on an unbounded query because it materializes the entire result set in memory.
Key Takeaways
- CRUD operations can be combined to build complete data-management workflows.
- Filters should identify the intended documents precisely.
- Projection reduces the fields returned to the application.
- Updates can target nested documents and array elements.
- Upserts, deletes, and bulk updates require careful filter and concurrency design.
Knowledge Check
Which operation should you use when changing only the nested field `instructor.city` while preserving the instructor's other fields?