Multi-Table Joins with $lookup & Array Flattening with $unwind0%

Multi-Table Joins with $lookup & Array Flattening with $unwind

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Multi-Table Joins with $lookup & Array Flattening with $unwind

Real-world reporting requires combining documents from disparate collections and manipulating nested arrays. The $lookup stage performs true server-side left outer joins between collections, and the $unwind stage deconstructs array fields into individual stream documents.


1. Multi-Collection Joins: The $lookup Stage

The $lookup stage performs a left outer join to an unsharded collection in the same database:

Output
Orders Collection ---> [$lookup from "users"] ---> Orders with embedded User details

Basic Syntax:

JavaScript
const orderDetails = await db.collection('orders').aggregate([
{
$lookup: {
from: 'users', // Target collection to join
localField: 'customerId', // Field from the input documents ('orders')
foreignField: '_id', // Field from documents of the 'from' collection ('users')
as: 'customerDetails' // Output array field name
}
}
]).toArray();

Note: $lookup always outputs an array in the as field, even if only one matching document is found.


2. Array Flattening: The $unwind Stage

Arrays often contain multiple elements that need to be analyzed individually. The $unwind stage deconstructs an array field from the input documents to output a document for each element in the array:

Output
Input Document:
{ _id: 1, item: "Course Bundle", tags: ["react", "node", "mongo"] }
 
After { $unwind: "$tags" }:
{ _id: 1, item: "Course Bundle", tags: "react" }
{ _id: 1, item: "Course Bundle", tags: "node" }
{ _id: 1, item: "Course Bundle", tags: "mongo" }

3. Combining $lookup, $unwind, and $group

Find the most popular course tags across all enrollments:

JavaScript
const popularTags = await db.collection('courses').aggregate([
// 1. Flatten the tags array
{ $unwind: '$tags' },
 
// 2. Group by individual tag and sum enrollments
{
$group: {
_id: '$tags',
courseCount: { $sum: 1 },
totalEnrollments: { $sum: '$enrollmentCount' }
}
},
 
// 3. Sort by popularity
{ $sort: { totalEnrollments: -1 } },
 
// 4. Return top 5 tags
{ $limit: 5 }
]);

Interactive Quiz

Multiple Choice Questions

Question 1
What type of relational join does the MongoDB $lookup aggregation stage perform?
Question 2
What data structure does the $lookup stage assign to the output field designated by as?
Question 3
What does the $unwind stage do when applied to an array with 4 elements?
Question 4
What happens by default in $unwind if a document has an empty array [] or the field is missing/null?
Question 5
Why should the foreignField in a joined $lookup collection be indexed?

Next Lesson

Database Indexing Strategies (Single, Compound, TTL) & Query Optimization

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext