MongoDB Query to Group Documents by Month
Use the MongoDB aggregation pipeline with
$group and extract the month using $month from a date field like { $group: { _id: { month: { $month: "$date" } }, count: { $sum: 1 } } } to group documents by month.Examples
Input[{ "date": ISODate("2023-01-15T00:00:00Z") }, { "date": ISODate("2023-01-20T00:00:00Z") }, { "date": ISODate("2023-02-10T00:00:00Z") }]
Output[{ "_id": { "month": 1 }, "count": 2 }, { "_id": { "month": 2 }, "count": 1 }]
Input[{ "date": ISODate("2023-12-01T00:00:00Z") }, { "date": ISODate("2023-12-15T00:00:00Z") }, { "date": ISODate("2023-11-30T00:00:00Z") }]
Output[{ "_id": { "month": 11 }, "count": 1 }, { "_id": { "month": 12 }, "count": 2 }]
Input[]
Output[]
How to Think About It
To group documents by month, first extract the month number from the date field using
$month. Then use $group to collect documents sharing the same month and count them. This groups all entries by their month value.Algorithm
1
Get the collection of documents with a date field.2
Extract the month number from each document's date using <code>$month</code>.3
Group documents by this month number using <code>$group</code>.4
Count the number of documents in each group.5
Return the grouped results with month and count.Code
mongodb
db.collection.aggregate([
{
$group: {
_id: { month: { $month: "$date" } },
count: { $sum: 1 }
}
}
])Output
[
{ "_id": { "month": 1 }, "count": 2 },
{ "_id": { "month": 2 }, "count": 1 }
]
Dry Run
Let's trace grouping three documents by month using their date field.
1
Extract month from each date
Dates: 2023-01-15, 2023-01-20, 2023-02-10 → Months: 1, 1, 2
2
Group documents by month
Group 1: two documents, Group 2: one document
3
Count documents in each group
Month 1 count: 2, Month 2 count: 1
| Month | Count |
|---|---|
| 1 | 2 |
| 2 | 1 |
Why This Works
Step 1: Extract month using $month
The $month operator pulls the month number (1-12) from each document's date field.
Step 2: Group by month with $group
The $group stage collects documents sharing the same month into one group.
Step 3: Count documents in each group
Using $sum: 1 counts how many documents fall into each month group.
Alternative Approaches
Group by year and month
mongodb
db.collection.aggregate([
{
$group: {
_id: {
year: { $year: "$date" },
month: { $month: "$date" }
},
count: { $sum: 1 }
}
}
])Groups by both year and month to separate same months in different years.
Group by formatted month string
mongodb
db.collection.aggregate([
{
$group: {
_id: { $dateToString: { format: "%Y-%m", date: "$date" } },
count: { $sum: 1 }
}
}
])Groups by year-month string for readable output but slightly slower.
Complexity: O(n) time, O(k) space
Time Complexity
The aggregation scans all n documents once to extract months and group them, so it is O(n).
Space Complexity
It uses extra space proportional to the number of unique months k, so O(k).
Which Approach is Fastest?
Grouping by numeric month is fastest; grouping by formatted strings is slower due to string operations.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Group by $month | O(n) | O(k) | Simple month grouping |
| Group by year and month | O(n) | O(k) | Distinguishing months across years |
| Group by formatted string | O(n) | O(k) | Readable year-month output |
Always ensure your date field is stored as a proper Date type for
$month to work correctly.Trying to group by month on a string date without converting it to a Date type causes errors or wrong results.