---
title: "How to Join Collections in MongoDB Using $lookup Aggregation?"  
description: "How to Join Collections in MongoDB Using $lookup Aggregation?"  
author: "Lily Chitlangiya"  
published: 2026-09-01  
updated: 2026-09-04  
canonical: https://answers.mindstick.com/qa/117130/how-to-join-collections-in-mongodb-using-lookup-aggregation  
category: "MongoDB"  
tags: ["mongodb", "aggregation", "database-joins", "NoSQL"]  
reading_time: 3 minutes  

---

# How to Join Collections in MongoDB Using $lookup Aggregation?

Coming from a relational database background, I need to query related documents stored in separate collections. How does the `$lookup` operator work in MongoDB's aggregation pipeline to join two collections?

## Understanding $lookup

The `$lookup` stage performs a left outer join to an unsharded collection in the same database, filtering in documents from the joined collection for processing.

- **localField:** The field from the input documents passed into the `$lookup` stage.
- **foreignField:** The field from the documents in the target collection.
- **as:** The name of the new array field added to input documents containing matches.

### Example Aggregation Pipeline

```
db.orders.aggregate([
    {
        $lookup: {
            from: "products",
            localField: "productId",
            foreignField: "_id",
            as: "productDetails"
        }
    }
]);
```

## Answers

### Answer by Ravi Vishwakarma

In MongoDB, although document databases are inherently schema-less and designed for denormalized data models, there are many scenarios where relational-style joins are required. MongoDB provides the **$lookup** stage in its Aggregation Framework to perform left outer joins between collections within the same database.

## Understanding the $lookup Aggregation Stage

The **$lookup** operator takes documents from an input collection (the primary collection being queried) and combines them with documents from another collection (the joined collection) based on a specified matching field or condition.

### Basic $lookup Syntax

The standard syntax for a basic equality join between two collections is structured as follows:

```
{
    "$lookup": {
        "from": "<collection_to_join>",
        "localField": "<field_from_input_docs>",
        "foreignField": "<field_from_from_collection_docs>",
        "as": "<output_array_field>"
    }
}
```

## Step-by-Step Practical Example

Consider a database with two collections: **orders** and **products**.

An order document in the `orders` collection look like this:

```
{
    "_id": 101,
    "item_id": 5001,
    "quantity": 2,
    "customer": "John Doe"
}
```

A product document in the `products` collection looks like this:

```
{
    "_id": 5001,
    "name": "Wireless Mouse",
    "price": 29.99
}
```

### Executing the Join Query

To join the `orders` collection with the `products` collection based on the matching product ID, use the following aggregation pipeline:

```
db.orders.aggregate([
    {
        "$lookup": {
            "from": "products",
            "localField": "item_id",
            "foreignField": "_id",
            "as": "product_details"
        }
    }
])
```

### Output Result

The aggregation query appends an array named `product_details` to each order document:

```
[
    {
        "_id": 101,
        "item_id": 5001,
        "quantity": 2,
        "customer": "John Doe",
        "product_details": [
            {
                "_id": 5001,
                "name": "Wireless Mouse",
                "price": 29.99
            }
        ]
    }
]
```

## Advanced $lookup with Pipeline and Search Conditions

MongoDB also allows uncorrelated subqueries and complex join conditions using custom pipeline stages inside **$lookup**.

```
db.orders.aggregate([
    {
        "$lookup": {
            "from": "products",
            "let": {
                "order_item": "$item_id",
                "order_qty": "$quantity"
            },
            "pipeline": [
                {
                    "$match": {
                        "$expr": {
                            "$and": [
                                { "$eq": ["$_id", "$$order_item"] },
                                { "$gte": ["$stock", "$$order_qty"] }
                            ]
                        }
                    }
                }
            ],
            "as": "matching_stock_products"
        }
    }
])
```

## Key Points to Remember

- The result of a **$lookup** operator is always returned as an array field in the output document.
- If no matching documents are found in the target collection, the output array will be empty (`[]`).
- You can follow a **$lookup** stage with an **$unwind** stage to flatten the array into individual document properties if needed.
- Ensure indexes exist on `foreignField` to optimize query performance during aggregation.


---

Original Source: https://answers.mindstick.com/qa/117130/how-to-join-collections-in-mongodb-using-lookup-aggregation

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
