Learning MongoDB: Grouping Data by Date for Time-Series Analysis


Effectively managing and analyzing time-series data is a critical requirement in modern application development and data science.
When handling vast datasets stored in MongoDB, a powerful NoSQL database, it becomes essential to consolidate and analyze documents based on various temporal components, such as the day, month, or year of a timestamp.
This analytical capability is vital for uncovering deep insights into data trends, identifying seasonal patterns, and tracking performance over time.
This comprehensive guide will demonstrate the precise methodology for leveraging MongoDB’s robust aggregation pipeline to group documents by specific date components, providing clear, practical examples and detailed explanations for each step.

The Core Syntax: Grouping Documents by Date

The foundational technique for grouping documents by date in MongoDB relies on the execution of the db.collection.aggregate() method.
At the heart of this operation is the $group stage, which is specifically designed to consolidate input documents into groups based on a defined grouping key.
To utilize date fields for this grouping key, we must first extract and transform the date components into a recognizable format, a task perfectly suited for the powerful $dateToString operator.

The primary syntax below serves as the definitive template for initiating a date-based aggregation query. This structure transforms a specified date field into a string format, which then becomes the unique identifier (the _id field) for each resulting group:

db.collection.aggregate([
  {$group:{ _id:{$dateToString:{format: "%Y-%m-%d", date: "$day"}}, count:{ $sum: 1}}}
])

Within this query, the $group stage processes the input stream of documents. The _id field is explicitly set to the output generated by $dateToString, which meticulously formats the value of the $day field into the standard “YYYY-MM-DD” string representation.
Furthermore, the expression count:{ $sum: 1} utilizes the $sum accumulator to calculate the total number of original documents consolidated within each unique date group. It is crucial to remember that $day must be replaced with the exact name of your date field within your MongoDB documents.

Preparing the Environment: The Sales Data Model

To effectively illustrate these aggregation concepts, we will establish a sample collection named sales.
This collection is designed to mimic real-world daily sales records, where each document contains a day field (stored as the BSON Date type) and an amount field representing the monetary value of the sale.
Populating this collection with sample documents will allow us to observe precisely how the aggregation pipeline processes and transforms practical data into meaningful summaries.

The commands provided below insert seven sample sales records into our sales collection. These records feature a diverse mix of dates and amounts, including deliberate duplication of dates to showcase the counting mechanism of the aggregation framework.
Understanding this input data is fundamental, as it forms the basis for interpreting the subsequent query results.

db.sales.insertOne({day: new Date("2020-01-20"), amount: 40})
db.sales.insertOne({day: new Date("2020-01-20"), amount: 25})
db.sales.insertOne({day: new Date("2020-01-21"), amount: 32})
db.sales.insertOne({day: new Date("2020-01-21"), amount: 18})
db.sales.insertOne({day: new Date("2020-01-22"), amount: 19})
db.sales.insertOne({day: new Date("2020-01-23"), amount: 29})
db.sales.insertOne({day: new Date("2020-01-24"), amount: 35})

These sample documents, once inserted, serve as the source material for our upcoming aggregation queries. They provide a tangible context for how date-based grouping functions when applied to real-world sales data, enabling us to track daily transactional volume.

Practical Aggregation: Counting Documents by Day

With the sales collection successfully populated, we can now execute our primary aggregation query. The goal of this initial query is to group all documents by their day field and simultaneously count the total number of sales that occurred on each unique date. This operation is fundamental for understanding the daily activity level within the dataset.

The following code snippet applies the necessary stages to achieve this grouping. It specifically uses the $dateToString operator to format the $day field into a daily string (YYYY-MM-DD), assigning this value to the _id grouping key. The total count for each group is then calculated efficiently using the $sum: 1 accumulator.

db.sales.aggregate([
  {$group:{ _id:{$dateToString:{format: "%Y-%m-%d", date: "$day"}}, count:{ $sum: 1}}}
]) 

Upon execution, the aggregation pipeline processes every document, extracting and normalizing the date information. Documents sharing the same formatted date are clustered together, and the $sum accumulator provides the final count for each distinct date group. This methodology offers an immediate, concise summary of activity.

The aggregation query returns the following results, clearly showing the number of sales records associated with each day:

{ _id: '2020-01-20', count: 2 }
{ _id: '2020-01-22', count: 1 }
{ _id: '2020-01-21', count: 2 } 
{ _id: '2020-01-23', count: 1 }
{ _id: '2020-01-24', count: 1 }

From this output, we gain immediate clarity on the distribution of sales:

  • The date 2020-01-20 recorded 2 sales transactions.
  • The date 2020-01-21 also recorded 2 sales transactions.
  • The dates 2020-01-22, 2020-01-23, and 2020-01-24 each recorded 1 sale transaction.

This grouped summary is invaluable for identifying immediate operational metrics, such as transactional volume per day.

Refining Analysis: Sorting Aggregation Results

While simple grouping and counting provide necessary metrics, effective data analysis often requires presenting these results in a specific, logical order. For example, analysts may need to quickly identify the days with the highest or lowest sales volume. This crucial step is accomplished by integrating the $sort stage immediately after the $group stage in the aggregation pipeline.

By chaining the $sort stage, we can order the output based on the newly calculated count field. To demonstrate sorting in ascending order (showing the least active days first), we use the value 1 for the sort parameter:

db.sales.aggregate([
  {$group:{_id:{$dateToString:{format: "%Y-%m-%d", date: "$day"}}, count:{ $sum: 1}}},
  {$sort: {count:1}} 
]) 

The command $sort: {count:1} ensures that the resulting documents are ordered numerically by the count field, starting from the lowest value. This query yields the following output:

{ _id: '2020-01-22', count: 1 }
{ _id: '2020-01-23', count: 1 }
{ _id: '2020-01-24', count: 1 }
{ _id: '2020-01-20', count: 2 }
{ _id: '2020-01-21', count: 2 } 

Conversely, to identify the most active sales days, we must sort the results in descending order. This simple modification requires changing the sort value for the count field from 1 to -1:

db.sales.aggregate([
  {$group:{_id:{$dateToString:{format: "%Y-%m-%d", date: "$day"}}, count:{ $sum: 1}}},
  {$sort: {count:-1}} 
]) 

This descending sort immediately highlights the peak activity periods, returning results that prioritize dates with the highest counts:

{ _id: '2020-01-20', count: 2 }
{ _id: '2020-01-21', count: 2 }
{ _id: '2020-01-22', count: 1 } 
{ _id: '2020-01-23', count: 1 }
{ _id: '2020-01-24', count: 1 }

By integrating the $sort stage, we transform raw counts into actionable insights, making it significantly easier to identify trends and outliers within the aggregated time-series data.

Advanced Temporal Grouping: Year, Month, and Week

The true power of the $dateToString operator lies in its versatility, allowing grouping beyond simple daily summaries. By adjusting the format string, developers can easily aggregate documents based on entirely different temporal granularities, such as year, month, or even week number.

To group documents exclusively by the year, which is invaluable for macro-level, long-term trend analysis, the %Y format specifier is used. In this example, we also change the accumulator to calculate the $sum of the sales $amount, rather than just counting documents:

db.sales.aggregate([
  {$group:{ _id:{$dateToString:{format: "%Y", date: "$day"}}, totalSales:{ $sum: "$amount"}}}
])

For a slightly more granular analysis, grouping by month is achieved using the %Y-%m format. This allows tracking monthly performance and identifying seasonal peaks or troughs with greater precision than yearly analysis:

db.sales.aggregate([
  {$group:{ _id:{$dateToString:{format: "%Y-%m", date: "$day"}}, monthlyCount:{ $sum: 1}}}
])

Finally, if the analytical requirement is to monitor activity on a weekly basis, the %Y-%U format specifier (representing the year and the week number) provides the perfect solution. This is highly effective for identifying weekly trends and cycles:

db.sales.aggregate([
  {$group:{ _id:{$dateToString:{format: "%Y-%U", date: "$day"}}, weeklyCount:{ $sum: 1}}}
])

By mastering these varying date format specifiers, developers can precisely tailor their aggregation pipeline queries to meet complex analytical demands, thereby unlocking deeper, multi-dimensional insights from their stored time-series data.

Conclusion: Mastering Date-Based Aggregation

Grouping documents by date stands as a fundamental pillar of data analysis within MongoDB, providing an efficient and scalable method for extracting meaningful information from time-stamped datasets.
By effectively utilizing the aggregation pipeline, particularly the combination of the $group stage and the $dateToString operator, developers and analysts can quickly count, sum, and analyze data across diverse temporal granularities, from daily metrics to annual summaries.

We have successfully covered the core syntax for daily grouping, established a practical sample dataset, and demonstrated how to count documents by date. Furthermore, we enhanced our analytical capabilities by incorporating the $sort stage, which facilitates the crucial identification of high and low activity periods. Finally, we explored the flexibility of $dateToString to group by year, month, or week, illustrating the adaptable nature of these powerful techniques.

The techniques detailed here provide a robust foundation that can be expanded for more sophisticated data aggregation tasks. To further refine results, developers should consider integrating additional pipeline stages, such as the $match stage to filter documents before grouping, or the $project stage to restructure and simplify the output documents. Continued experimentation with these operators will ensure that you unlock the full analytical potential of MongoDB’s aggregation framework for your specific business intelligence needs.

Additional Resources

The following tutorials explain how to perform other common operations in MongoDB:

Cite this article

Mohammed looti (2025). Learning MongoDB: Grouping Data by Date for Time-Series Analysis. PSYCHOLOGICAL STATISTICS. Retrieved from https://statistics.arabpsychology.com/mongodb-group-by-date/

Mohammed looti. "Learning MongoDB: Grouping Data by Date for Time-Series Analysis." PSYCHOLOGICAL STATISTICS, 31 Oct. 2025, https://statistics.arabpsychology.com/mongodb-group-by-date/.

Mohammed looti. "Learning MongoDB: Grouping Data by Date for Time-Series Analysis." PSYCHOLOGICAL STATISTICS, 2025. https://statistics.arabpsychology.com/mongodb-group-by-date/.

Mohammed looti (2025) 'Learning MongoDB: Grouping Data by Date for Time-Series Analysis', PSYCHOLOGICAL STATISTICS. Available at: https://statistics.arabpsychology.com/mongodb-group-by-date/.

[1] Mohammed looti, "Learning MongoDB: Grouping Data by Date for Time-Series Analysis," PSYCHOLOGICAL STATISTICS, vol. X, no. Y, ص Z-Z, October, 2025.

Mohammed looti. Learning MongoDB: Grouping Data by Date for Time-Series Analysis. PSYCHOLOGICAL STATISTICS. 2025;vol(issue):pages.

Download Post (.PDF)
Scroll to Top