Aggregation Expressions
Date Expressions
$year, $month, $dayOfMonth and $dateToString for grouping and display.
BSON dates are UTC instants. Reports want calendar buckets: month, day, YYYY-MM. Extract parts, or format a string, then $group on that. Do not $group on the raw createdAt unless you meant exact milliseconds.
db.orders.aggregate([
{
$group: {
_id: { year: { $year: "$createdAt" }, month: { $month: "$createdAt" } },
revenue: { $sum: "$amount" }
}
}
])db.orders.aggregate([
{ $match: { status: { $in: ["shipped", "delivered"] } } },
{
$group: {
_id: { $dateToString: { format: "%Y-%m", date: "$createdAt" } },
revenue: { $sum: "$amount" },
orders: { $sum: 1 }
}
},
{ $sort: { _id: 1 } }
]){ _id: "2026-07", revenue: 210000, orders: 40 }
{ _id: "2026-08", revenue: 185000, orders: 36 }| Operator | Use |
|---|---|
| $year / $month / $dayOfMonth | Numeric parts; $dayOfWeek is 1=Sunday |
| $dateToString | format: %Y-%m-%d, %H, timezone: "Asia/Kolkata" |
| $dateTrunc | 5.0+: { unit: "month" } — cleaner than a string if you can use it |
timezone on $dateToString / $year is how Bangalore's 12:30 AM on the 1st does not fall in the previous UTC day. Omit it and you group in UTC. $add milliseconds to a date is duration; $dateAdd / $dateDiff (5.0) are the readable form. Filter status with $match before you group by month — cancelled orders do not belong in revenue.
Interview question
How do you group documents by calendar month in MongoDB?
Put a date expression in $group _id: $dateToString with format %Y-%m, or { year: { $year: "$createdAt" }, month: { $month: "$createdAt" } }. $dateTrunc with unit month on 5.0+. Apply timezone if the calendar is not UTC. Filter statuses before grouping so cancelled orders are not in the sum.
Practice
Filter statuses, then group on a YYYY-MM string.