MongoDB Query to Calculate Percentage of a Field
$group to sum values and then $project to calculate percentage like { $multiply: [{ $divide: ["$value", "$total"] }, 100] }.Examples
How to Think About It
$group to sum and $project to calculate percentages.Algorithm
Code
db.collection.aggregate([
{ $group: { _id: null, total: { $sum: "$value" } } },
{ $lookup: {
from: "collection",
pipeline: [],
as: "docs"
}
},
{ $unwind: "$docs" },
{ $project: {
category: "$docs.category",
percentage: { $multiply: [ { $divide: ["$docs.value", "$total"] }, 100 ] }
}
}
])Dry Run
Let's trace the example with documents [{category: 'A', value: 30}, {category: 'B', value: 70}] through the aggregation.
Calculate total sum
Sum values: 30 + 70 = 100
Join total to each document
Each document now has total = 100
Calculate percentage
For 'A': (30 / 100) * 100 = 30%, for 'B': (70 / 100) * 100 = 70%
| category | value | total | percentage |
|---|---|---|---|
| A | 30 | 100 | 30 |
| B | 70 | 100 | 70 |
Why This Works
Step 1: Summing values
The $group stage adds all value fields to get the total sum.
Step 2: Joining total to documents
Using $lookup and $unwind, the total sum is attached to each document for calculation.
Step 3: Calculating percentage
The $project stage divides each document's value by the total and multiplies by 100 to get the percentage.
Alternative Approaches
db.collection.aggregate([
{ $facet: {
total: [ { $group: { _id: null, total: { $sum: "$value" } } } ],
data: [ { $project: { category: 1, value: 1 } } ]
}
},
{ $unwind: "$total" },
{ $unwind: "$data" },
{ $project: {
category: "$data.category",
percentage: { $multiply: [ { $divide: ["$data.value", "$total.total"] }, 100 ] }
}
}
])// Fetch total sum first const total = db.collection.aggregate([{ $group: { _id: null, total: { $sum: "$value" } } }]).toArray()[0].total; // Then fetch documents and calculate percentage in application code
Complexity: O(n) time, O(n) space
Time Complexity
The aggregation scans all documents once to sum values and then processes each document to calculate percentages, resulting in O(n) time.
Space Complexity
Extra space is used to hold the aggregation pipeline state and output, proportional to the number of documents, so O(n).
Which Approach is Fastest?
Calculating total and percentages in one pipeline is efficient; client-side calculation requires multiple queries and more network overhead.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Single aggregation pipeline | O(n) | O(n) | All-in-one server-side calculation |
| $facet method | O(n) | O(n) | Parallel calculation but more complex |
| Client-side calculation | O(n) + network | O(n) | Simple aggregation but requires multiple queries |