📖 Scenario: You are managing a MongoDB database for a bookstore. There are two collections: books and reviews. Each book has an _id and a title. The reviews collection stores customer reviews with fields book_id (referencing books._id), rating (1 to 5), and comment.You want to create a query that joins books with their reviews, but only includes reviews with a rating of 4 or higher. Also, you want to calculate the average rating for each book from these filtered reviews.
🎯 Goal: Build a MongoDB aggregation pipeline using $lookup with a pipeline to join books with filtered reviews (rating ≥ 4), and add a field averageHighRating showing the average of these high ratings.
📋 What You'll Learn
Create a books collection with exactly 3 books with specified _id and title.
Create a reviews collection with exactly 5 reviews referencing the books, with various ratings.
Write an aggregation on books using $lookup with a pipeline to join only reviews with rating >= 4.
Add a field averageHighRating to each book showing the average rating of the joined reviews.
💡 Why This Matters
🌍 Real World
Filtering and joining related data with conditions is common in real-world databases, such as showing only positive reviews for products.
💼 Career
Understanding $lookup with pipeline is important for MongoDB developers to write efficient and powerful queries for complex data relationships.
Progress0 / 4 steps
1
Create the books collection with 3 books
Insert these exact documents into a collection called books: { _id: 1, title: "The Great Gatsby" }, { _id: 2, title: "1984" }, and { _id: 3, title: "To Kill a Mockingbird" }.
MongoDB
Hint
Use db.books.insertMany() with an array of the 3 book documents.
Use db.reviews.insertMany() with an array of the 5 review documents.
3
Write the aggregation with $lookup using a pipeline
Write an aggregation on books using db.books.aggregate() with a $lookup stage. Use the pipeline option inside $lookup to join only reviews where rating is greater than or equal to 4. Use let to pass bookId as $_id from books to the pipeline. Store the joined reviews in a field called highRatedReviews.
MongoDB
Hint
Use $lookup with let to pass bookId, then in pipeline use $match with $expr to filter reviews by book_id and rating ≥ 4.
4
Add averageHighRating field with average rating of joined reviews
Extend the aggregation pipeline by adding a $addFields stage after $lookup. Create a new field called averageHighRating that calculates the average of the rating values in the highRatedReviews array using $avg. If there are no high rated reviews, the average should be null.
MongoDB
Hint
Use $addFields with averageHighRating set to { $avg: "$highRatedReviews.rating" }.
Practice
(1/5)
1. What is the main purpose of using $lookup with a pipeline in MongoDB?
easy
A. To create indexes on joined collections automatically
B. To update documents in the joined collection
C. To perform advanced joins with filtering and transformations on the joined data
D. To delete documents from multiple collections at once
Solution
Step 1: Understand $lookup basic function
$lookup is used to join documents from another collection into the current one.
Step 2: Role of pipeline in $lookup
Using a pipeline allows filtering and transforming the joined documents before adding them.
Final Answer:
To perform advanced joins with filtering and transformations on the joined data -> Option C
Quick Check:
$lookup with pipeline = advanced join [OK]
Hint: Remember: pipeline lets you filter joined data inside $lookup [OK]
Common Mistakes:
Thinking $lookup with pipeline updates or deletes data
Confusing $lookup with index creation
Assuming $lookup merges collections permanently
2. Which of the following is the correct syntax to define variables for use inside the pipeline of a $lookup stage?
easy
A. "params: { var1: \"$field1\", var2: \"$field2\" }"
B. "vars: { var1: \"$field1\", var2: \"$field2\" }"
C. "variables: [ var1: \"$field1\", var2: \"$field2\" ]"
D. "let: { var1: \"$field1\", var2: \"$field2\" }"
Solution
Step 1: Recall $lookup variable syntax
Variables for the pipeline are defined using the let keyword as an object.
Step 2: Match correct keyword and structure
Only let with an object of key-value pairs is valid syntax.
Final Answer:
"let: { var1: \"$field1\", var2: \"$field2\" }" -> Option D
Quick Check:
Variables in $lookup pipeline = let [OK]
Hint: Use 'let' keyword with object to define variables in $lookup [OK]
Common Mistakes:
Using 'vars' or 'variables' instead of 'let'
Using array syntax instead of object for variables
Omitting the $ sign before field names
3. Given collections orders and products, what will be the output of this aggregation on orders?
A. Variable reference inside $expr should be "$$empId" instead of "$empId"
B. The let keyword is not allowed inside $lookup
C. The from field must be an array, not a string
D. The as field cannot be named employeeInfo
Solution
Step 1: Check variable usage in $expr
Variables defined in let must be referenced with double dollar signs $$ inside the pipeline.
Step 2: Identify incorrect variable reference
The code uses "$empId" instead of "$$empId", causing a runtime error.
Final Answer:
Variable reference inside $expr should be "$$empId" instead of "$empId" -> Option A
Quick Check:
Use $$ to reference let variables inside pipeline [OK]
Hint: Use double $$ to reference let variables inside pipeline [OK]
Common Mistakes:
Using single $ instead of double $$ for let variables
Misplacing let outside $lookup
Incorrect data type for 'from' field
5. You want to join orders with products but only include products priced above 100 in the joined array. Which $lookup pipeline correctly achieves this?