0
0
MongodbHow-ToBeginner · 2 min read

MongoDB Query to Find Average Per Group Using Aggregation

Use the MongoDB aggregation pipeline with $group and $avg operators like this: db.collection.aggregate([{ $group: { _id: "$groupField", averageValue: { $avg: "$valueField" } } }]) to find the average per group.
📋

Examples

Input[{ category: "fruit", price: 10 }, { category: "fruit", price: 20 }, { category: "vegetable", price: 30 }]
Output[{ _id: "fruit", averageValue: 15 }, { _id: "vegetable", averageValue: 30 }]
Input[{ type: "A", score: 50 }, { type: "A", score: 70 }, { type: "B", score: 90 }, { type: "B", score: 110 }]
Output[{ _id: "A", averageValue: 60 }, { _id: "B", averageValue: 100 }]
Input[]
Output[]
🧠

How to Think About It

To find the average per group, first decide which field you want to group by. Then, for each group, calculate the average of the target numeric field. MongoDB's aggregation framework lets you group documents by a field and apply the $avg operator to compute the average value within each group.
📐

Algorithm

1
Identify the field to group documents by.
2
Use the aggregation pipeline with a $group stage.
3
In the $group stage, set _id to the group field.
4
Use $avg to calculate the average of the target numeric field for each group.
5
Return the grouped results with their average values.
💻

Code

mongodb
db.sales.aggregate([
  {
    $group: {
      _id: "$category",
      averagePrice: { $avg: "$price" }
    }
  }
])
Output
[ { "_id": "fruit", "averagePrice": 15 }, { "_id": "vegetable", "averagePrice": 30 } ]
🔍

Dry Run

Let's trace the aggregation on a sample collection with documents having categories and prices.

1

Group documents by category

Group all documents with category 'fruit' together and those with 'vegetable' together.

2

Calculate average price per group

For 'fruit', average (10 + 20) / 2 = 15; for 'vegetable', average is 30.

CategoryPricesAverage Price
fruit[10, 20]15
vegetable[30]30
💡

Why This Works

Step 1: Grouping with $group

The $group stage collects documents sharing the same value in the specified field, here category.

Step 2: Calculating average with $avg

Within each group, $avg computes the mean of the price field values.

🔄

Alternative Approaches

Using Map-Reduce
mongodb
db.sales.mapReduce(
  function() { emit(this.category, this.price); },
  function(key, values) { return Array.avg(values); },
  { out: "average_prices" }
)
Map-Reduce is more complex and slower than aggregation but can be used for custom calculations.
Using $group with $sum and $count
mongodb
db.sales.aggregate([
  {
    $group: {
      _id: "$category",
      total: { $sum: "$price" },
      count: { $sum: 1 }
    }
  },
  {
    $project: {
      averagePrice: { $divide: ["$total", "$count"] }
    }
  }
])
Manually calculates average by dividing sum by count, useful if you want more control.

Complexity: O(n) time, O(k) space

Time Complexity

The aggregation scans all n documents once to group them, so time is O(n).

Space Complexity

Space depends on the number of groups k, as it stores intermediate results per group.

Which Approach is Fastest?

The aggregation pipeline with $group and $avg is faster and more readable than map-reduce.

ApproachTimeSpaceBest For
Aggregation $group + $avgO(n)O(k)Simple average per group, best performance
Map-ReduceO(n)O(k)Complex custom calculations, slower
Aggregation $group + $sum/$countO(n)O(k)Manual average calculation, more control
💡
Always use the aggregation framework's $group and $avg operators for efficient average calculations per group.
⚠️
Beginners often forget to set the _id field in $group, which is required to specify the grouping key.