DEV Community

Cover image for MongoDB Aggregation Roadmap – A 7-Day Study Plan
Rayan Hossain
Rayan Hossain

Posted on • Edited on

MongoDB Aggregation Roadmap – A 7-Day Study Plan

MongoDB’s Aggregation Framework is more than just querying data — it’s about analyzing, transforming, and connecting collections to unlock powerful insights.

This 7-day study guide is designed to take you from beginner to confident user, with daily lessons, examples, practice problems, and projects.

Day 1 – $match & $project

Examples:

Find all Bangladeshi users:

db.users.aggregate([
  { $match: { country: "Bangladesh" } }
]);
Enter fullscreen mode Exit fullscreen mode

Show only name & email:

db.users.aggregate([
  { $project: { 
    _id: 0, 
    fullName: { $concat: ["$firstName", " ", "$lastName"] }, 
    email: 1 
  }}
]);
Enter fullscreen mode Exit fullscreen mode

Find users younger than 25:

db.users.aggregate([
  { $match: { age: { $lt: 25 } } }
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Find all users from the USA.
  2. Show only firstName and age of all users.
  3. Find products cheaper than 100.
  4. Show only name and category for products.

Day 2 – $sort, $limit, $skip

Examples:

Sort products by price descending:

db.products.aggregate([
  { $sort: { price: -1 } }
]);
Enter fullscreen mode Exit fullscreen mode

Get 2 youngest users:

db.users.aggregate([
  { $sort: { age: 1 } }, 
  { $limit: 2 }
]);
Enter fullscreen mode Exit fullscreen mode

Skip first order, show next 2:

db.orders.aggregate([
  { $skip: 1 }, 
  { $limit: 2 }
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Get the top 2 most expensive products.
  2. Get the oldest 1 user.
  3. Sort orders by createdAt newest first.
  4. Show 2nd and 3rd most expensive products.

Day 3 – $group

Examples:

Total orders by status:

db.orders.aggregate([
  { $group: { _id: "$status", total: { $sum: 1 } } }
]);
Enter fullscreen mode Exit fullscreen mode

Average price per category:

db.products.aggregate([
  { $group: { _id: "$category", avgPrice: { $avg: "$price" } } }
]);
Enter fullscreen mode Exit fullscreen mode

Total revenue:

db.orders.aggregate([
  { $group: { _id: null, totalRevenue: { $sum: "$amount" } } }
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Count users per country.
  2. Find min & max product price.
  3. Count how many reviews each product has.
  4. Find the average age of all users.

Day 4 – $addFields & $unwind

Examples:

Add fullName field:

db.users.aggregate([
  { $addFields: { 
    fullName: { $concat: ["$firstName", " ", "$lastName"] } 
  }}
]);
Enter fullscreen mode Exit fullscreen mode

Unwind product tags:

db.products.aggregate([
  { $unwind: "$tags" }
]);
Enter fullscreen mode Exit fullscreen mode

Count number of tags per product:

db.products.aggregate([
  { $project: { name: 1, tagCount: { $size: "$tags" } } }
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Add a field isAdult = true if age >= 18.
  2. Unwind orders by productId.
  3. Count how many tags contain the word "tech".
  4. Add field priceWithTax = price * 1.15.

Day 5 – $lookup

Examples:

Join users with orders:

db.users.aggregate([
  { $lookup: { 
    from: "orders", 
    localField: "_id", 
    foreignField: "userId", 
    as: "userOrders" 
  }}
]);
Enter fullscreen mode Exit fullscreen mode

Join products with reviews:

db.products.aggregate([
  { $lookup: { 
    from: "reviews", 
    localField: "_id", 
    foreignField: "productId", 
    as: "productReviews" 
  }}
]);
Enter fullscreen mode Exit fullscreen mode

Users with their orders and products:

db.orders.aggregate([
  { $lookup: { 
    from: "users", 
    localField: "userId", 
    foreignField: "_id", 
    as: "user" 
  }},
  { $lookup: { 
    from: "products", 
    localField: "productId", 
    foreignField: "_id", 
    as: "product" 
  }}
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Join orders with products to show product details.
  2. Join reviews with users to show reviewer info.
  3. Join users → orders → products (nested join).
  4. Find users with at least 1 shipped order.

Day 6 – $lookup with Pipelines

Examples:

Only shipped orders per user:

db.users.aggregate([
  {
    $lookup: {
      from: "orders",
      let: { uid: "$_id" },
      pipeline: [
        { $match: { 
          $expr: { 
            $and: [
              { $eq: ["$userId", "$$uid"] }, 
              { $eq: ["$status", "shipped"] }
            ] 
          }
        }}
      ],
      as: "shippedOrders"
    }
  }
]);
Enter fullscreen mode Exit fullscreen mode

Latest order per user:

db.users.aggregate([
  {
    $lookup: {
      from: "orders",
      let: { uid: "$_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$userId", "$$uid"] } } },
        { $sort: { createdAt: -1 } },
        { $limit: 1 }
      ],
      as: "latestOrder"
    }
  }
]);
Enter fullscreen mode Exit fullscreen mode

Practice Questions:

  1. Get only reviews with a rating >= 4 for each product.
  2. For each user, get only pending orders.
  3. For each product, get the latest review.
  4. For each user, get orders in the last 7 days.

Day 7 – Real Projects

Mini Project 1 – E-commerce Dashboard

Create queries to find:

  • Total revenue
  • Top 2 categories by sales
  • Average order value
  • Number of shipped vs pending orders

Mini Project 2 – User Analytics

Create queries to find:

  • Active users per country
  • Users with more than 1 order
  • Users with average order amount > 100

Mini Project 3 – Product Insights

Create queries to find:

  • Products with the highest average rating
  • Top 2 most reviewed products
  • Products with tags "tech" and "home"

Tips for Success

  1. Practice Daily: Try to write 2-3 aggregation queries each day
  2. Start Simple: Begin with basic $match and $project, then build complexity
  3. Use MongoDB Compass: Visual query builder helps understand pipeline stages
  4. Test with Sample Data: Use MongoDB sample datasets or create your own test data
  5. Read Documentation: MongoDB's aggregation documentation is excellent
  6. Debug Step by Step: Add one stage at a time to see intermediate results

Common Operators Reference

Stage Purpose Example
$match Filter documents { $match: { age: { $gte: 18 } } }
$project Select/transform fields { $project: { name: 1, _id: 0 } }
$group Group by field(s) { $group: { _id: "$category", count: { $sum: 1 } } }
$sort Sort results { $sort: { createdAt: -1 } }
$limit Limit results { $limit: 10 }
$skip Skip documents { $skip: 5 }
$lookup Join collections { $lookup: { from: "orders", ... } }
$unwind Deconstruct arrays { $unwind: "$tags" }
$addFields Add new fields { $addFields: { total: { $add: ["$price", "$tax"] } } }

Sample Data for Practice

📁 users.json

[
  { "_id": 1, "firstName": "Rayan", "lastName": "Hossain", "email": "rayan@example.com", "age": 24, "country": "Bangladesh" },
  { "_id": 2, "firstName": "Sanjida", "lastName": "Juie", "email": "juie@example.com", "age": 27, "country": "Bangladesh" },
  { "_id": 3, "firstName": "John", "lastName": "Doe", "email": "john@example.com", "age": 30, "country": "USA" },
  { "_id": 4, "firstName": "Alice", "lastName": "Smith", "email": "alice@example.com", "age": 22, "country": "USA" },
  { "_id": 5, "firstName": "David", "lastName": "Khan", "email": "david@example.com", "age": 35, "country": "India" },
  { "_id": 6, "firstName": "Sophia", "lastName": "Rahman", "email": "sophia@example.com", "age": 19, "country": "Bangladesh" },
  { "_id": 7, "firstName": "Michael", "lastName": "Lee", "email": "michael@example.com", "age": 40, "country": "USA" },
  { "_id": 8, "firstName": "Sara", "lastName": "Ahmed", "email": "sara@example.com", "age": 28, "country": "Bangladesh" }
]

Enter fullscreen mode Exit fullscreen mode

📁 products.json

[
  { "_id": 101, "name": "Laptop Pro", "category": "tech", "price": 1200, "tags": ["tech", "office"] },
  { "_id": 102, "name": "Smartphone X", "category": "tech", "price": 800, "tags": ["tech", "mobile"] },
  { "_id": 103, "name": "Coffee Maker", "category": "home", "price": 90, "tags": ["home", "kitchen"] },
  { "_id": 104, "name": "Gaming Chair", "category": "furniture", "price": 250, "tags": ["tech", "home"] },
  { "_id": 105, "name": "Headphones", "category": "tech", "price": 150, "tags": ["tech", "music"] },
  { "_id": 106, "name": "Table Lamp", "category": "home", "price": 40, "tags": ["home", "decor"] },
  { "_id": 107, "name": "Backpack", "category": "fashion", "price": 60, "tags": ["fashion", "travel"] },
  { "_id": 108, "name": "Shoes", "category": "fashion", "price": 70, "tags": ["fashion", "casual"] }
]
Enter fullscreen mode Exit fullscreen mode

📁 orders.json

[
  { "_id": 201, "userId": 1, "productId": 101, "amount": 1200, "status": "shipped", "createdAt": ISODate("2025-09-20T10:00:00Z") },
  { "_id": 202, "userId": 2, "productId": 103, "amount": 90, "status": "pending", "createdAt": ISODate("2025-09-21T14:30:00Z") },
  { "_id": 203, "userId": 3, "productId": 102, "amount": 800, "status": "shipped", "createdAt": ISODate("2025-09-19T09:15:00Z") },
  { "_id": 204, "userId": 4, "productId": 105, "amount": 150, "status": "shipped", "createdAt": ISODate("2025-09-18T18:20:00Z") },
  { "_id": 205, "userId": 5, "productId": 104, "amount": 250, "status": "pending", "createdAt": ISODate("2025-09-17T11:45:00Z") },
  { "_id": 206, "userId": 6, "productId": 106, "amount": 40, "status": "shipped", "createdAt": ISODate("2025-09-22T07:10:00Z") },
  { "_id": 207, "userId": 7, "productId": 107, "amount": 60, "status": "shipped", "createdAt": ISODate("2025-09-16T20:55:00Z") },
  { "_id": 208, "userId": 8, "productId": 108, "amount": 70, "status": "shipped", "createdAt": ISODate("2025-09-15T13:40:00Z") }
]
Enter fullscreen mode Exit fullscreen mode

📁 reviews.json

[
  { "_id": 301, "productId": 101, "userId": 1, "rating": 5, "comment": "Excellent laptop!", "createdAt": ISODate("2025-09-21T09:00:00Z") },
  { "_id": 302, "productId": 101, "userId": 3, "rating": 4, "comment": "Very good performance.", "createdAt": ISODate("2025-09-20T12:30:00Z") },
  { "_id": 303, "productId": 102, "userId": 4, "rating": 3, "comment": "Battery life could be better.", "createdAt": ISODate("2025-09-19T15:45:00Z") },
  { "_id": 304, "productId": 103, "userId": 2, "rating": 5, "comment": "Makes great coffee!", "createdAt": ISODate("2025-09-18T10:15:00Z") },
  { "_id": 305, "productId": 104, "userId": 5, "rating": 4, "comment": "Comfortable chair.", "createdAt": ISODate("2025-09-17T11:50:00Z") },
  { "_id": 306, "productId": 105, "userId": 6, "rating": 2, "comment": "Sound quality not good.", "createdAt": ISODate("2025-09-16T09:20:00Z") },
  { "_id": 307, "productId": 106, "userId": 7, "rating": 4, "comment": "Nice design.", "createdAt": ISODate("2025-09-15T18:10:00Z") },
  { "_id": 308, "productId": 107, "userId": 8, "rating": 5, "comment": "Perfect travel backpack.", "createdAt": ISODate("2025-09-14T16:00:00Z") }
]

Enter fullscreen mode Exit fullscreen mode

How to Import Sample Data

Using MongoDB Shell:

mongoimport --db ecommerce --collection users --file users.json --jsonArray
mongoimport --db ecommerce --collection products --file products.json --jsonArray
mongoimport --db ecommerce --collection orders --file orders.json --jsonArray
mongoimport --db ecommerce --collection reviews --file reviews.json --jsonArray
Enter fullscreen mode Exit fullscreen mode

Using MongoDB Compass:

  1. Create a new database called testdb
  2. Create collections: users, products, orders
  3. Import JSON files into respective collections

Verify Data Import:

// Check if data is imported correctly
db.users.countDocuments()    // Should return 4
db.products.countDocuments() // Should return 4
db.orders.countDocuments()   // Should return 4
Enter fullscreen mode Exit fullscreen mode

Happy Learning! 🚀

Top comments (2)

Collapse
 
prime_1 profile image
Roshan Sharma

Nice post! Solid 7-day roadmap, makes MongoDB aggregation way easier to grasp.

Collapse
 
rayan2228 profile image
Rayan Hossain

Thank you, brother