MongoDB
aggregation
$lookup
query optimization
field projection

MongoDB aggregation with lookup only include or project some fields to return from query

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When dealing with MongoDB aggregations, one of the operations you might encounter is $lookup. This operator is used to perform joins between collections, which can be a powerful way to consolidate related data into a single result. However, retrieving related data using $lookup without careful consideration of performance and data size can lead to inefficient queries. This is where projections with $lookup come into play, allowing you to include only certain fields in the result to optimize performance and data handling.

Understanding $lookup

In MongoDB, $lookup is an aggregation stage that lets you join documents from one collection into another. It is akin to performing a left outer join in relational databases. The $lookup stage adds a new array field to each input document, containing matching documents from the specified collection.

Syntax Example

json
1{
2  "$lookup": {
3    "from": "otherCollection",
4    "localField": "fieldFromInput",
5    "foreignField": "fieldFromOther",
6    "as": "outputArray"
7  }
8}

Here:

  • from: The collection to perform the join with.
  • localField: The field from the documents of the input collection.
  • foreignField: The field from the from collection.
  • as: The name of the array field in which the joined documents will be stored.

Projections in $lookup

Projections are used to specify which fields to include or exclude in the result set. When performing a $lookup, projections can be particularly useful, especially if the from collection contains documents with numerous fields, some of which are not needed. By explicitly defining which fields to include, you reduce the amount of data passed over the network and improve the performance of your query.

To project specific fields from a $lookup operation, you would use the pipeline option within $lookup. Instead of just specifying the from, localField, and foreignField, you also include the pipeline option, which allows for further processing.

Syntax with Projection

json
1{
2  "$lookup": {
3    "from": "otherCollection",
4    "let": { "localUserId": "$userId" },
5    "pipeline": [
6      {
7        "$match": { "$expr": { "$eq": ["$foreignUserId", "`$$localUserId"] } }
8      },
9      { "$project": { "field1": 1, "field2": 1, "_id": 0 } }
10    ],
11    "as": "outputArray"
12  }
13}

In this example:

  • let: Defines variables that can be referenced in the pipeline stages.
  • $expr and $eq: Used to allow the use of aggregation expressions in the $match stage.
  • $project: Used within the pipeline to specify that only field1 and field2 should be included, while _id is excluded.

Advantages of Using Projections with $lookup

  1. Optimized Network Usage: By limiting the fields returned from the joined documents, you reduce the network payload.
  2. Improved Query Performance: Smaller result sets mean faster query responses and reduced memory consumption.
  3. Enhanced Clarity: Returning only relevant fields makes the data easier to consume and process in the application layer.
  4. Reduced Data Processing: You avoid transferring and processing unnecessary fields, which can be especially beneficial when dealing with large datasets or complex nested documents.

Practical Example

Consider two collections, orders and customers, where you want to retrieve orders along with their corresponding customer names and email addresses. The orders collection contains the customer ID as a reference, while the customers collection has details of each customer.

Orders Collection Example

json
1{
2  "_id": 1,
3  "customerId": "A123",
4  "orderTotal": 250
5}

Customers Collection Example

json
1{
2  "_id": "A123",
3  "name": "John Doe",
4  "email": "[email protected]",
5  "address": "123 Main St"
6}

Aggregation Pipeline

json
1[
2  {
3    "$lookup": {
4      "from": "customers",
5      "let": { "custId": "$customerId" },
6      "pipeline": [
7        { "$match": { "$expr": { "$eq": ["$_id", "$$`custId"] } } },
8        { "$project": { "name": 1, "email": 1, "_id": 0 } }
9      ],
10      "as": "customerDetails"
11    }
12  }
13]

Result

json
1[
2  {
3    "_id": 1,
4    "customerId": "A123",
5    "orderTotal": 250,
6    "customerDetails": [
7      {
8        "name": "John Doe",
9        "email": "[email protected]"
10      }
11    ]
12  }
13]

Here, only the name and email fields from the customers collection are included in the result, optimizing the amount of data being processed and transferred.

Summary of Key Points

FeatureBenefit
$lookup with projectionReduces unnecessary data
Only include necessary fieldsOptimizes performance and speed
Minimized network payloadEnhances efficiency
Simplifies result set processingFacilitates easier consumption

Conclusion

Using the $lookup operation with projections in MongoDB aggregations enhances the efficiency and efficacy of your queries by limiting the data fields returned. This optimizes resource usage and addresses performance bottlenecks, especially when dealing with large datasets or highly nested documents. With careful design and consideration, $lookup projections can significantly improve the way you handle related data in MongoDB, making your applications more responsive and resource-efficient.


Course illustration
Course illustration

All Rights Reserved.