$lookup & $unwind
$lookup & $unwind
Section titled “$lookup & $unwind”$lookup joins documents from another collection. $unwind flattens arrays.
$lookup Basic Syntax
Section titled “$lookup Basic Syntax”{ $lookup: { from: "users", localField: "userId", foreignField: "_id", as: "user" }}Join Orders With Users
Section titled “Join Orders With Users”db.orders.aggregate([ { $lookup: { from: "users", localField: "userId", foreignField: "_id", as: "user" } }])The result contains user as an array:
{ _id: ObjectId("..."), userId: ObjectId("..."), totalAmount: 2500, user: [ { _id: ObjectId("..."), name: "Alice" } ]}$unwind
Section titled “$unwind”$unwind converts each array element into a separate document.
db.orders.aggregate([ { $lookup: { from: "users", localField: "userId", foreignField: "_id", as: "user" } }, { $unwind: "$user" }])Preserve Empty Arrays
Section titled “Preserve Empty Arrays”Use this when a missing match should not remove the document.
{ $unwind: { path: "$user", preserveNullAndEmptyArrays: true } }$lookup With Pipeline
Section titled “$lookup With Pipeline”Use pipeline form when the join needs filters, projections, or multiple conditions.
db.users.aggregate([ { $lookup: { from: "orders", let: { userId: "$_id" }, pipeline: [ { $match: { $expr: { $eq: ["$userId", "$$userId"] } } }, { $match: { status: "completed" } }, { $project: { totalAmount: 1, createdAt: 1 } } ], as: "completedOrders" } }])Common $unwind Use Case
Section titled “Common $unwind Use Case”Flatten order items:
db.orders.aggregate([ { $unwind: "$items" }, { $group: { _id: "$items.productId", totalSold: { $sum: "$items.quantity" } } }])