![]() |
VOOZH | about |
The $lookup stage in MongoDB performs a left outer join between collections, enabling relational-like queries within the aggregation framework to combine related data from multiple collections.
Here are some usage discussed below:
{
$lookup: {
from: <foreignCollection>,
localField: <fieldInInputDocument>,
foreignField: <fieldInForeignDocument>,
as: <outputArrayField>
}
}
We need a collection and some documents on which we will perform various operations and queries. Here we will consider a collection called orders and customers which contains various information shown as below:
Collection: orders
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86e"),
"order_number": "ORD001",
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"customer_details": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
}
]
},
// Other order documents...
]
Collection: customers
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
},
// Other customer documents...
]
Retrieve orders from the orders collection along with corresponding customer details from the customers collection based on matching customer_id and _id.
db.orders.aggregate([
{
$lookup: {
from: "customers",
localField: "customer_id",
foreignField: "_id",
as: "customer_details"
}
}
])
Output:
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86e"),
"order_number": "ORD001",
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"customer_details": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
}
]
},
// Other order documents with appended customer details...
]
By default, $lookup always adds the output array field, and if no match is found, it returns an empty array for that document.
db.orders.aggregate([
{
$lookup: {
from: "customers",
let: { customerId: "$customer_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$_id", "$$customerId"] }
}
}
],
as: "customer_details"
}
}
])
Output:
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86e"),
"order_number": "ORD001",
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"customer_details": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
}
]
},
// Other order documents...
]
Multiple $lookup stages can be used in a single pipeline to join data from different collections, such as enriching orders with customer and product details.
db.orders.aggregate([
{
$lookup: {
from: "customers",
localField: "customer_id",
foreignField: "_id",
as: "customer_info"
}
},
{
$addFields: {
customer_details: {
$mergeObjects: { $arrayElemAt: ["$customer_info", 0] }
}
}
}
])
Output:
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86e"),
"order_number": "ORD001",
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"customer_info": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
}
],
"customer_details": {
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com"
}
},
// Other order documents...
]
$lookup lets you join data from multiple collections in one aggregation pipeline, improving query efficiency and performance.
db.orders.aggregate([
{
$lookup: {
from: "customers",
let: { customerId: "$customer_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$_id", "$$customerId"] }
}
},
{
$lookup: {
from: "products",
localField: "_id",
foreignField: "customer_id",
as: "products_ordered"
}
}
],
as: "customer_details"
}
}
])
Output:
[
{
"_id": ObjectId("60f9d7ac345b7c9df348a86e"),
"order_number": "ORD001",
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"customer_details": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"name": "John Doe",
"email": "john@example.com",
"products_ordered": [
{
"_id": ObjectId("60f9d7ac345b7c9df348a870"),
"customer_id": ObjectId("60f9d7ac345b7c9df348a86d"),
"product_name": "Product A"
}
]
}
]
},
// Other order documents...
]