liveBook · Manning

$lookup

As explained in MongoDB 8.0 in Action, Third Edition

$lookup is an aggregation pipeline stage that performs a left outer join with documents from another collection.

$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

How MongoDB 8.0 in Action, Third Edition covers it

How deep it goes
Explains equality-join parameters and works through flattening and view pipelines, while warning about join costs rather than detailing execution internals.
Examples
Demonstrates transaction-to-account enrichment and a transaction-to-customer view using collections in `sample_analytics`.
What it assumes
Assumes familiarity with collections and aggregation pipelines while specifying each field required for an equality join.
What you can do after
Build it from scratch with MongoDB aggregation to enrich transactions, flatten joined fields, or define an enriched view.
How it connects
Connects $lookup to aggregation pipelines, MongoDB views, $unwind, $mergeObjects, denormalization, and $unionWith.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of MongoDB 8.0 in Action, Third Edition. The section links point to the parts of the book it draws on.