MongoDB and Document Stores
Schemaless data with a fee you discover on day 90
MongoDB stores flexible JSON-shaped documents, shards by a key across replicas, and trades strict multi-document transactions for horizontal write scale. The document model, indexes, and shard key decide everything.
What you will learn
- Model one-to-many relationships with documents instead of joins
- Explain why the shard key is a permanent decision
- Write an aggregation pipeline that a report needs
What is this?
MongoDB persists BSON documents that can nest objects, arrays, and vary across rows, in collections. Reads can hit a single or a sharded cluster; the document model means related data often lives in one document so many operations are single-document and atomic-ish. Replica sets and shards need a deliberate strategy.
Why do you need it?
- Teams need a flexible store for product catalogs, event details, or single-view data when the schema changes weekly.
- The document model beats relational joins for deeply nested polymorphic records.
- A wrong shard key is permanent and explodes in hot partitions; worth understanding before you ship.
Mental model
A box of index cards, each card self-contained
A document (BSON object)
An order and its line items, contact details, and notes all live on one card. Reads grab one card instead of joining five tables; updates must rewrite the card wholesale.
How it works
- Documents are BSON; each _id is a PK; indexes work on embedded fields and array elements (multikey).
- A replica set maintains primary + secondaries; reads can opt into secondary reads (eventual).
- Sharding splits a collection by a chosen shard key range across shards; the key must be selective and evenly distributed.
- Multi-document transactions exist but require replica sets (MongoDB 4.0+) and come with op-log/abort costs.
- The aggregation pipeline ($match, $group, $lookup, $unwind) does server-side reduction of documents.
A sharded collection across three shards.
Key commands
db.orders.createIndex({ customer.email: 1, createdAt: -1 });Composite index on an embedded field and date for the report shape.
db.orders.explain("executionStats").find({ _id: 1 });Inspect the actual query plan and scanned documents.
sh.enableSharding("shop"); sh.shardCollection("shop.orders", { _id: "hashed" });Shard by a hashed key to spread writes if a range key would be hot.
Examples
Document model vs joined relation
db.orders.insertOne({ _id: 1, customer: { name: "Ada", email: "ada@example.com" }, items: [ { sku: "A1", qty: 2 }, { sku: "B2", qty: 1 } ], status: "pending", createdAt: new Date("2026-01-15T09:00:00Z")}) db.orders.aggregate([ { $match: { createdAt: { $gte: new Date("2026-01-01") } } }, { $unwind: "$items" }, { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" } } }, { $sort: { qty: -1 } },])One document carries the whole order; the pipeline reduces nested arrays into a by-SKU totals report without a JOIN.
In production
- An e-commerce cart stores each cart as one document, atomically updated in a single write.
- A catalog ingests irregular manufacturer specs nested per product, with secondary indexes per spec field.
- A device-IoT fleet shards by hashed device_id so housekeeping loads spread evenly.
Best practices
- Design documents around access patterns: the hottest read should be one document fetch.
- Pick a shard key that is selective, evenly distributed, and stable; re-capping a hot key is a painful migration.
- Keep documents bounded (< 16MB) and watch growth factors like never-ending arrays.
- Let optional $lookup do the occasional join instead of normalizing everything upfront.
Common mistakes
- Sharding by a low-cardinality key (status, region) and creating one hot shard.
- Storing per-lineitem documents when the app always reads the whole order — joins now happen in code.
- Believing the flexible schema absolves you of schema evolution (data-quality and validation gates still exist).
Debugging tips
- Permanent caches and .explain('executionStats') separate 'not using the index' from 'index is the wrong shape'.
- A growing hot shard usually means the shard key ranges are skewed; check chunk distributions.
- For slow appends, look at oplog size and secondary lag — a stalled replica delays failover safety.
Interview checkpoint
Hands-on lab
- Run MongoDB in Docker and insert a nested document
- Build a composite index on embedded fields
- Prove plan usage with explain("executionStats")
Model, Index, and Query Documents
30 min · intermediate
Quick quiz
Which scenario suits a document store best?
A low-cardinality shard key can create a single hot shard.