Chapter 20: MongoDB Aggregation $lookup

1. What is $lookup? (Big picture – very clear explanation)

$lookup is MongoDB’s version of SQL LEFT OUTER JOIN (with some extra superpowers).

It lets you:

For each document in the source collection (the left side), look up matching documents from another collection (the right side), and attach those matching documents as an array field in the output.

Key points teacher repeats three times:

  • It is always a left outer join — every document from the source collection survives (even if no matches → you get empty array [])
  • The joined data comes as an array (even if only one match — it’s still [ {…} ])
  • It can be very expensive if not used carefully → indexes, small result sets, early $match are your best friends
  • Introduced in MongoDB 3.2 (2015) → massively improved in 3.6+ (let pipeline, uncorrelated subqueries)

2. Basic Syntax – The Classic / Most Common Form (Equality Join)

JavaScript

After this stage → every document now has an extra field (the as name) which is an array of matching documents from the other collection.

3. Hands-on Example – Classic Use Case (Orders + Users)

Let’s create two small collections:

JavaScript

Now — enrich orders with user information:

JavaScript

Sample output:

JSON

→ Notice: order ORD004 (non-existing user) still appears → left outer join behavior

4. Advanced & Modern $lookup (MongoDB 3.6+ → Very Powerful)

Since MongoDB 3.6 you can use let + pipeline syntax — this is much more flexible:

JavaScript

Advantages of let + pipeline style:

  • You can do non-equality joins (e.g., range, regex, $expr conditions)
  • You can add $match, $project, $sort inside the lookup → much less data transferred
  • Better performance in many cases

5. Quick Reference Table – $lookup Cheat Sheet

Goal Which syntax? Key fields / options Important notes
Classic equality join (user ← orders) Classic (local/foreign) from, localField, foreignField, as Fastest when fields are indexed
Join + filter / project only needed fields let + pipeline let + pipeline array inside Preferred in 2026 – more control
Non-equality join (e.g. date range) let + pipeline $expr inside sub-pipeline Very powerful but slower
Handle single match (not array) After $lookup $addFields: { field: { $arrayElemAt: [“$field”, 0] } } Almost always done
Avoid large arrays Inside pipeline $limit: 1, $project only needed fields Critical for performance

6. Mini Exercise – Try Right Now!

  1. Join orders with users using classic syntax → see the array
  2. Convert the customer array to single object using $arrayElemAt
  3. Show only orders from Hyderabad users (add $matchbefore or after lookup – compare)
  4. Try the let + pipeline version – project only name and city

Understood beta? $lookup is the stage that makes MongoDB feel like it has relationships — but remember: use it carefully, index the foreignField, filter early, project only what you need — or your database will cry on Valentine’s Day.

Next class options:

  • How to index for $lookup (huge perf difference)
  • Uncorrelated subqueries in $lookup (MongoDB 5.0+ magic)
  • $lookup + $unwind + $group pattern (very common)
  • Or let’s finally build a complete “E-commerce Order Report” with joins, counts, sorting, limits?

Tell me what you want next — class is ready! 🚀❤️

Any part of $lookup confusing? Ask anything — we’ll do more live examples together 😄

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *