In this lesson, you will learn how to simulate SQL-style joins in a document database by manually stitching together related data using application-level logic.
Beyond the Server-Side Join
In relational databases, you are accustomed to the JOIN keyword, which allows the database engine to automatically combine rows from two tables based on a common column. Document databases are fundamentally different; they are designed for horizontal scalability, which makes complex, cross-collection joins expensive and non-performant.
When you use the Referencing Join Pattern, you accept that the database will not provide a "JOIN" operator. Instead, you manage the relationship between documents yourself using application code.
The Two-Step Retrieval
Imagine you have a users collection and an orders collection. The orders document contains a user_id field. To fetch an order along with its user's details, you must perform two distinct queries.
- Fetch the primary document: Find the order in the
orderscollection. - Extract the reference: Take the
user_idfrom that order. - Fetch the related document: Query the
userscollection using thatuser_id.
// Step 1: Get the order
const order = db.orders.findOne({ _id: orderId });
// Step 2: Use the reference to get the user
const user = db.users.findOne({ _id: order.user_id });
// Step 3: Combine them in application memory
const completeRecord = {
...order,
owner: user
};
Why Do This?
This pattern is essential when you have "Many-to-Many" or "One-to-Many" relationships where the data is too large to embed directly. By keeping the collections separate, you ensure that individual documents remain under the BSON size limit and can be updated independently.
While it requires more trips to the database, you can mitigate latency by using an _id index on the target collection, ensuring the second lookup is an extremely fast O(1) or O(log n) operation. The "Join" logic resides in your code, which allows you to handle cases where the referenced document might be missing—a scenario the database engine would normally hide from you.
Key Takeaway: The Referencing Join Pattern shifts the responsibility of data association from the database engine to your application code by performing sequential lookups to reassemble related documents in memory.