$lookup is an aggregation pipeline stage that performs a left outer join with another collection in the same database. It adds an array of matching documents to each input document, so later stages can process related data together. For example, transactions can gain account or customer details for financial reports. section 6.2
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
For an equality join, set `from` to the collection being joined, `localField` to the input field, `foreignField` to the matching field in that collection, and `as` to the new array field. section 6.2
Enrich and flatten transactions
Join `transactions` to `accounts` on `account_id`, placing matches in `account_details`. If the desired result is one combined document, follow $lookup with $unwind, then use $mergeObjects in $replaceRoot and remove the temporary array with $unset. The linked pipeline shows the stages in order. section 6.2.2
db.transactions.aggregate([
{
$lookup: {
from: "accounts", // Joining from the
➥accounts collection
localField: "account_id", // Field from
➥transactions collection
foreignField: "account_id", // Field from the
➥accounts collection
as: "account_details"
}
},
{
$unwind: "$account_details" // Unwind the result
➥to merge objects properly
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: ["$account_details", "$$ROOT"]
➥// Merging the account details into the transaction
}
}
},
{
$unset: "account_details" // Remove the account_details
➥field from the final output
}
])
Use this complete aggregation pipeline when the joined account fields should be merged into each transaction rather than left in an array. section 6.2.2
Expose an enriched view
A read-only view can join `transactions` to `customers`, extract customer fields from the resulting array with $arrayElemAt, and discard the temporary array. Query the view with find(); MongoDB computes it during reads. A view-definition pipeline cannot contain $out or $merge, including inside an embedded $lookup pipeline. section 6.2.1
Listing 6.6 Creating a MongoDB view with $lookup
// Connect to the sample_analytics database use sample_analytics // Create a view named 'enriched_transactions' within ➥the 'sample_analytics' database db.createView("enriched_transactions", "transactions", [ { // Lookup to join 'transactions' with 'customers' based on ➥matching account_id $lookup: { from: "customers", localField: "account_id", foreignField: "accounts", as: "customer_details" } }, { // Extract customer details $set: { "Customer Name": { $arrayElemAt: ["$customer_details.name", 0] }, "Customer Email": { $arrayElemAt: ["$customer_details.email", 0] }, "Customer Address": { $arrayElemAt: ➥["$customer_details.address", 0] }, "Customer Tier and Benefits": { $arrayElemAt: ➥["$customer_details.tier_and_details", 0] } } }, { // Remove the temporary 'customer_details' field no longer ➥needed after extraction $unset: "customer_details" } ])
The view definition shows $lookup followed by $set and $unset to expose selected customer details. section 6.2.1
Use joins selectively: repeated $lookup operations can make large queries slow and difficult to maintain. Consider denormalization when frequent joins outweigh the benefits of separate collections. Place an appropriate $match early to reduce work for later stages. Choose $unionWith instead when the goal is to combine whole collections into one stream, not match related documents. section 6.2.2 section 6.1.2
