In this lesson, you will learn how to determine when it is architecturally advantageous to nest related data inside a single document rather than separating it into distinct collections.
The Locality Principle
In document databases, the primary goal of embedding is data locality. When you embed related data directly within a parent document, you ensure that all information required to represent an entity is retrieved in a single disk I/O operation. Unlike relational databases, where you must perform costly JOIN operations to stitch data together, embedding allows the database to serve a complete object immediately.
When to Embed
You should choose to embed related data when it meets these three criteria:
- "Contains" Relationship: The data naturally forms part of the parent entity. For example, a
Userhas multipleAddresses. An address rarely exists meaningfully outside the context of a specific user. - Read-Heavy Access: Your application almost always needs the parent and the child data together. If you find yourself constantly querying the parent and then immediately querying the child collection, embedding reduces your network round-trips.
- Stability and Size: The embedded data is relatively stable and does not grow boundlessly. MongoDB documents have a size limit (typically 16MB), so avoid embedding data that grows indefinitely, such as an ever-expanding audit log.
Concrete Illustration
Consider an e-commerce order system. If an Order only ever needs its LineItems when the order is viewed, embedding is ideal:
{
"_id": "order_123",
"customer_id": "user_99",
"status": "shipped",
"line_items": [
{ "sku": "book-001", "qty": 1, "price": 15.00 },
{ "sku": "pen-002", "qty": 2, "price": 2.50 }
]
}
In this case, retrieving the document order_123 provides the full context in one go. If you were to store line_items in a separate collection, you would lose the benefit of atomic reads and require an application-level merge of two data streams.
However, if line_items were to reach thousands of entries or if they needed to be accessed independently by inventory systems, you would move toward a referenced model instead.
Key Takeaway: Embed data when it is logically contained by the parent and accessed as a single, immutable unit of work to minimize I/O overhead.