MongoDB Exercises
Three short MongoDB exercises - schema design, aggregation, and indexing.
Three short challenges
EXAMPLE
// 1. Schema for a small marketplace - orders + items + payments
// Decide: embed vs reference for items. Hint: bounded list per order, embed.
// Orders collection
{
_id: ObjectId('...'),
customerId: ObjectId('...'),
status: 'paid', // open | paid | shipped | cancelled
items: [
{ sku: 'A-100', qty: 2, unitPrice: 19.95 },
{ sku: 'B-770', qty: 1, unitPrice: 49.00 }
],
total: 88.90,
payment: { provider: 'stripe', chargeId: 'ch_abc' },
createdAt: ISODate(),
paidAt: ISODate()
}
// Indexes
db.orders.createIndex({ customerId: 1, createdAt: -1 });
db.orders.createIndex({ status: 1, createdAt: -1 });
// 2. Aggregation - revenue by month, last 12 months
db.orders.aggregate([
{ $match: { status: 'paid', paidAt: { $gte: new Date(Date.now() - 365 * 86_400_000) } } },
{
$group: {
_id: { y: { $year: '$paidAt' }, m: { $month: '$paidAt' } },
revenue: { $sum: '$total' },
orders: { $sum: 1 }
}
},
{ $sort: { '_id.y': 1, '_id.m': 1 } },
{
$project: {
_id: 0,
month: { $dateFromParts: { year: '$_id.y', month: '$_id.m', day: 1 } },
revenue: 1,
orders: 1
}
}
]);
// 3. Diagnose a slow query
// db.orders.find({ status: 'paid' }).sort({ createdAt: -1 }).limit(50).explain('executionStats');
// Look at executionStats:
// - totalDocsExamined vs nReturned (should be near 1:1)
// - stage: IXSCAN (good) vs COLLSCAN (bad)
// - executionTimeMillis
// Fix: ensure { status: 1, createdAt: -1 } compound index is the chosen one.
// The order of fields matters: equality fields first, then sort field.
// Stretch
// - Add a TTL index to auto-delete orders in 'open' state after 7 days
// - Convert one frequent aggregation into a materialised view with $merge
Why it matters
Three drills hit the parts of Mongo that matter daily - schema decisions, aggregation, and indexing. Reach for embed when the list is bounded; reach for references when it grows; always read explain when a query slows down.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Fill in the missing operator.
db.products.find({ price: { ____: 50 } });
Try it Yourself »
Discussion
Loading…