Lesson 0001 · The document model
The document is the unit of three things at once — storage, atomicity, and schema design. Get that one fact and embedding, "data accessed together stored together," and "when do I even need a transaction?" all derive themselves.
You already know the relational model cold: you normalize — split an entity across tables so each fact lives once — and then join at read time to put it back together. A clustered index (InnoDB) or a heap plus secondary indexes (Postgres) stores the rows; foreign keys wire the tables together. MongoDB makes the opposite first move, and this lesson is the keystone the whole course hangs off. Get it and a surprising amount derives itself: why you embed instead of join, why one write can be atomic without a transaction while another can't, and why "design for your access pattern" is the whole game.
The basic unit of data in MongoDB is a document: an ordered set of field-and-value pairs, stored as BSON — a binary superset of JSON with more types (dates, 64-bit ints, binary, ObjectId). — MongoDB Manual: "MongoDB stores data records as BSON documents. BSON is a binary representation of JSON documents, though it contains more data types than JSON." A value can itself be a document, an array, or an array of documents — so a document is a tree, not a flat row. Documents live in collections (loosely, the table); a collection needs no fixed schema.
Every document has an _id field that acts as its primary
key and is unique within the collection; if you don't supply one, the driver
generates an ObjectId.
— MongoDB Manual: "each document stored in a collection requires a unique _id field that acts as a primary key … If … omitted … the driver automatically generates an ObjectId for the _id field."
And a single document is capped: 16 MB — a deliberate limit so one
document can't hog RAM or bandwidth.
— MongoDB Manual: "The maximum BSON document size is 16 megabytes … helps ensure that a single document cannot use an excessive amount of RAM or … bandwidth."
The core principle of MongoDB data modeling is that data that is accessed together should be stored together. — MongoDB Manual: "A key principle of data modeling in MongoDB is that data that is accessed together should be stored together." So the default move is embedding: nest the related data inside the one document you'll read. That turns a multi-table join into a single-document lookup and avoids complex joins … while improving performance. — MongoDB Manual: "Embedding data … lets you avoid application joins, which reduces queries … and improves read performance."
Here is where the document being the unit of storage pays off as the unit of atomicity. A write to a single document is atomic — all-or-nothing — even when it touches many fields or nested arrays. — MongoDB Manual: "In MongoDB, a write operation is atomic on the level of a single document, even if the operation modifies multiple embedded documents within a single document." So if you embedded the order and its line-items in one document, updating the order and its items together is atomic for free — no transaction needed.
The moment your write must change more than one document atomically, the free ride ends: each document's change is still atomic, but the operation as a whole is not, and other operations can interleave. For true multi-document atomicity you reach for a distributed transaction. — MongoDB Manual: "When a single write operation … modifies multiple documents, the modification of each document is atomic, but the operation as a whole is not atomic. … For situations that require atomicity of reads and writes to multiple documents … MongoDB supports distributed transactions." And MongoDB's own guidance is telling: a transaction costs more than a single-document write, and its availability should not be a replacement for effective schema design — often, embedding removes the need entirely. — MongoDB Manual: "In most cases, multi-document transactions incur a greater performance cost … and the availability of transactions should not be a replacement for effective schema design."
In Postgres/InnoDB, atomicity is a property of the transaction — you wrap
N statements across M tables in BEGIN … COMMIT and the engine's MVCC +
undo/redo make them all-or-nothing. In MongoDB, atomicity is a property of the
document first: shape your data so the thing that changes together lives in
one document, and you get atomicity without paying for a transaction. Same goal —
consistency — reached from opposite starting points: the transaction vs
the document boundary.
Embedding is the default, not a law. You reference instead (store
an _id and look it up in another collection — the closest thing to a
foreign key) when the related data is large, grows without bound, or is accessed on
its own. The manual's example: an e-commerce product embeds its five most-recent
reviews for the product page, but keeps the full review history in a separate
collection because older reviews aren't accessed as frequently.
— MongoDB Manual: "store … reviews … in a separate collection if … not accessed as frequently."
Two forces pull against embedding: the 16 MB ceiling (an unbounded
array will eventually blow it) and duplication (embedded copies must be updated in
every place they were copied). We give schema design its own lesson (0006) — for now,
hold the shape: embed what you read together; reference what's big or independent.
| Question | Postgres / InnoDB (you know this) | MongoDB (this course) |
|---|---|---|
| Unit of data? | A row in a fixed-schema table | A document (BSON tree) in a collection |
| Schema? | Declared up front, enforced | Flexible — shape per document |
| Relate data by… | Normalize + join at read | Embed (or reference) — store together |
| Read one entity = | JOIN across tables | Fetch one document |
| Atomicity is a property of… | The transaction | The document (single-doc = atomic) |
| Multi-entity atomic write? | Always a transaction | Transaction — or embed so you don't need one |
Answer from memory — the effortful recall is what builds retention. Feedback is immediate.
What is the fundamental unit of data in MongoDB?
A write that modifies many fields and nested arrays of one document is:
The core principle that decides how to model data in MongoDB is:
You must atomically update three separate documents. What does MongoDB require?
Which pressure most directly pushes you to reference instead of embed?
No Mongo handy yet, so this is a lab to run later (Docker:
docker run --rm -p 27017:27017 mongo, then mongosh). It
makes the whole lesson visible in a few commands:
db.posts.insertOne({ title: "Hello",
author: { name: "Ann" },
comments: [ { user: "Bo", text: "hi" } ] }) // one embedded document
db.posts.findOne() // _id was auto-generated as an ObjectId
db.posts.updateOne({ title: "Hello" },
{ $push: { comments: { user: "Cy", text: "yo" } },
$set: { "author.name": "Ann B." } }) // touches array + nested field — ATOMIC, no txn
db.posts.findOne() // both changes applied together
That one updateOne changing a nested field and an array
together, atomically, with no transaction — that is the keystone made
concrete. Bring the output to your teacher and we'll read it together.
MongoDB Manual — Documents
(short; the BSON, _id, and 16 MB facts), then
Data Modeling for
the "accessed together, stored together" principle and embedding vs referencing.
For the atomicity boundary, Atomicity and Transactions
is two screens and worth reading in full.