How to Left Join in MongoDB
- Understanding Left Joins in MongoDB
- Using the $lookup Operator
- Filtering Results After Joining
- Aggregating Data with Additional Stages
- Conclusion
- FAQ

MongoDB is a powerful NoSQL database that allows for flexible data modeling. One of the key functionalities that developers often seek is the ability to perform joins between collections. While MongoDB does not support traditional SQL joins directly, you can achieve similar results using the $lookup
aggregation stage.
This tutorial will guide you through the concept of left joins in MongoDB, helping you understand how to combine data from multiple collections efficiently. Whether you’re building an application or just looking to enhance your database skills, this article will provide valuable insights and practical examples.
Understanding Left Joins in MongoDB
In a relational database, a left join retrieves all records from the left table and the matched records from the right table. If there is no match, the result is NULL on the side of the right table. In MongoDB, you can mimic this behavior using the $lookup
stage in an aggregation pipeline. This allows you to combine documents from two collections based on a specified field.
For instance, consider two collections: orders
and customers
. If you want to retrieve all orders along with the customer details, even if some orders do not have a matching customer, you would use a left join. The $lookup
operator is your tool for this task, allowing you to specify the local and foreign fields to join on.
Using the $lookup Operator
To perform a left join in MongoDB, you will primarily use the $lookup
operator. This operator allows you to join documents from different collections based on a common field. Here’s how you can do it:
db.orders.aggregate([
{
"$lookup": {
"from": "customers",
"localField": "customer_id",
"foreignField": "_id",
"as": "customer_info"
}
}
])
In this example, we are aggregating the orders
collection and using $lookup
to join it with the customers
collection. The localField
is customer_id
from the orders
collection, while the foreignField
is _id
from the customers
collection. The results will be stored in a new field called customer_info
.
Output:
[
{
"_id": 1,
"order_number": "A123",
"customer_id": "C1",
"customer_info": [
{
"_id": "C1",
"name": "John Doe"
}
]
},
{
"_id": 2,
"order_number": "A124",
"customer_id": "C2",
"customer_info": [
{
"_id": "C2",
"name": "Jane Smith"
}
]
},
{
"_id": 3,
"order_number": "A125",
"customer_id": "C3",
"customer_info": []
}
]
In the output, you can see that for the third order where customer_id
is C3
, the customer_info
array is empty. This indicates that there was no matching customer for that order, effectively mimicking the behavior of a left join.
Filtering Results After Joining
Sometimes, you may want to filter the results after performing a left join. You can achieve this by adding a $match
stage after the $lookup
. This allows you to refine your results based on specific criteria. Here’s how you can do it:
db.orders.aggregate([
{
"$lookup": {
"from": "customers",
"localField": "customer_id",
"foreignField": "_id",
"as": "customer_info"
}
},
{
"$match": {
"customer_info.0": { "$exists": True }
}
}
])
In this snippet, we are looking for orders that have customer information available. The $match
stage filters the results, ensuring that only orders with associated customer details are returned.
Output:
[
{
"_id": 1,
"order_number": "A123",
"customer_id": "C1",
"customer_info": [
{
"_id": "C1",
"name": "John Doe"
}
]
},
{
"_id": 2,
"order_number": "A124",
"customer_id": "C2",
"customer_info": [
{
"_id": "C2",
"name": "Jane Smith"
}
]
}
]
Here, the output only includes orders that have a corresponding customer, excluding any orders without a match. This gives you the flexibility to manage your data effectively.
Aggregating Data with Additional Stages
In more complex scenarios, you might want to perform additional aggregation stages after the $lookup
. This could include sorting, grouping, or projecting specific fields. Here’s an example that demonstrates how to do this:
db.orders.aggregate([
{
"$lookup": {
"from": "customers",
"localField": "customer_id",
"foreignField": "_id",
"as": "customer_info"
}
},
{
"$unwind": {
"path": "$customer_info",
"preserveNullAndEmptyArrays": True
}
},
{
"$group": {
"_id": "$customer_info.name",
"total_orders": { "$sum": 1 }
}
}
])
In this example, after performing the $lookup
, we use $unwind
to deconstruct the customer_info
array. This allows us to group the results by customer name and count the total number of orders for each customer.
Output:
[
{
"_id": "John Doe",
"total_orders": 1
},
{
"_id": "Jane Smith",
"total_orders": 1
},
{
"_id": None,
"total_orders": 1
}
]
The output shows the total number of orders associated with each customer. If a customer does not exist, it returns None
, indicating that the order was made without a corresponding customer.
Conclusion
In summary, performing a left join in MongoDB is straightforward using the $lookup
operator. By understanding how to aggregate data from multiple collections, you can create more dynamic queries that yield meaningful insights. Whether you’re filtering results or aggregating data further, MongoDB provides powerful tools to manage your data effectively. With these techniques, you can enhance your database skills and improve your applications’ data handling capabilities.
FAQ
-
What is a left join in MongoDB?
A left join in MongoDB is achieved using the$lookup
operator, which allows you to combine documents from two collections based on a specified field. -
Can I filter results after performing a left join?
Yes, you can use the$match
stage after the$lookup
to filter results based on specific criteria. -
What happens if there is no matching document in the right collection?
If there is no match, the resulting array from the left join will be empty for that document, mimicking the behavior of a traditional left join. -
How can I aggregate data after a left join?
You can use additional aggregation stages like$unwind
,$group
, and$sort
after the$lookup
to manipulate and analyze your data further. -
Is it possible to join more than two collections?
Yes, you can perform multiple$lookup
operations in a single aggregation pipeline to join more than two collections.
Aminul Is an Expert Technical Writer and Full-Stack Developer. He has hands-on working experience on numerous Developer Platforms and SAAS startups. He is highly skilled in numerous Programming languages and Frameworks. He can write professional technical articles like Reviews, Programming, Documentation, SOP, User manual, Whitepaper, etc.
LinkedIn