DEV Community

keshav Sandhu
keshav Sandhu

Posted on

MongoDB aggregation Pipelines simplified

MongoDB Aggregation Pipeline stages

MongoDB’s aggregation pipeline is a powerful framework for transforming, filtering, and analyzing data in collections similar to SQL’s GROUP BY, JOIN, WHERE, etc.


🧱 Basic Structure

An aggregation pipeline is an array of stages, each stage transforms the documents and passes them to the next stage.

db.collection.aggregate([
  { <stage1> },
  { <stage2> },
  ...
])
Enter fullscreen mode Exit fullscreen mode

1️⃣ $match - Filtering Documents

Works like the find() query. Filters documents based on conditions.

Example:

db.orders.aggregate([
  { $match: { status: "delivered" } }
])
Enter fullscreen mode Exit fullscreen mode

✅ Returns only documents where status = "delivered".


2️⃣ $project - Select or Reshape Fields

Used to include/exclude fields or create computed fields.

Example:

db.orders.aggregate([
  { 
    $project: { 
      _id: 0,
      item: 1,
      total: { $multiply: ["$price", "$quantity"] }
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Outputs only item and a computed field total.


3️⃣ $group - Group Documents & Aggregate Data

Groups documents by a key and applies aggregation operators (like $sum, $avg, etc.).

Example:

db.orders.aggregate([
  {
    $group: {
      _id: "$customerId",
      totalSpent: { $sum: { $multiply: ["$price", "$quantity"] } },
      numOrders: { $sum: 1 }
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Groups by customer and calculates:

  • Total spent
  • Number of orders

4️⃣ $sort - Sort Results

Sorts documents by one or more fields.

Example:

db.orders.aggregate([
  { $sort: { total: -1 } }  // descending
])
Enter fullscreen mode Exit fullscreen mode

✅ Sorts by total in descending order.


5️⃣ $limit and $skip - Pagination

  • $limit: Restricts the number of documents.
  • $skip: Skips a number of documents.

Example:

db.orders.aggregate([
  { $sort: { date: -1 } },
  { $skip: 10 },
  { $limit: 5 }
])
Enter fullscreen mode Exit fullscreen mode

✅ Skips first 10, returns next 5 (useful for pagination).


6️⃣ $unwind - Deconstruct Arrays

Splits array fields into multiple documents (one per element).

Example:

db.orders.aggregate([
  { $unwind: "$items" }
])
Enter fullscreen mode Exit fullscreen mode

✅ If a document has an array items: [a, b, c], it becomes 3 documents - one for each item.


7️⃣ $lookup - Join with Another Collection

Performs a left outer join between two collections.

Example:

db.orders.aggregate([
  {
    $lookup: {
      from: "customers",
      localField: "customerId",
      foreignField: "_id",
      as: "customer"
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Adds matching customer info to each order under the field customer.


8️⃣ $addFields - Add or Modify Fields

Adds new fields or modifies existing ones.

Example:

db.orders.aggregate([
  {
    $addFields: {
      total: { $multiply: ["$price", "$quantity"] },
      statusUpper: { $toUpper: "$status" }
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Adds computed total and uppercase status.


9️⃣ $count - Count Documents

Counts the number of documents in the pipeline.

Example:

db.orders.aggregate([
  { $match: { status: "pending" } },
  { $count: "pendingOrders" }
])
Enter fullscreen mode Exit fullscreen mode

✅ Returns { pendingOrders: 12 }.


🔟 $facet - Multiple Pipelines in One

Allows parallel aggregations on the same dataset.

Example:

db.orders.aggregate([
  {
    $facet: {
      totalByCustomer: [
        { $group: { _id: "$customerId", total: { $sum: "$amount" } } }
      ],
      avgOrderValue: [
        { $group: { _id: null, avg: { $avg: "$amount" } } }
      ]
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Runs two aggregations in one pipeline.


1️⃣1️⃣ $bucket - Categorize Into Ranges

Groups values into defined ranges (buckets).

Example:

db.sales.aggregate([
  {
    $bucket: {
      groupBy: "$amount",
      boundaries: [0, 100, 500, 1000],
      default: "Other",
      output: { count: { $sum: 1 } }
    }
  }
])
Enter fullscreen mode Exit fullscreen mode

✅ Categorizes sales by amount ranges.


1️⃣2️⃣ $out - Write Results to a Collection

Saves aggregation results into a new collection.

Example:

db.orders.aggregate([
  { $match: { status: "completed" } },
  { $out: "completedOrders" }
])
Enter fullscreen mode Exit fullscreen mode

✅ Writes output into a new collection completedOrders.


1️⃣3️⃣ $merge - Merge Results into an Existing Collection

Similar to $out, but can update or insert documents.

Example:

db.orders.aggregate([
  { $group: { _id: "$customerId", total: { $sum: "$amount" } } },
  { $merge: { into: "customerTotals", whenMatched: "merge", whenNotMatched: "insert" } }
])
Enter fullscreen mode Exit fullscreen mode

✅ Updates or inserts aggregated data into customerTotals.

Let me know if this helped you in some way.

Top comments (0)