A Node.js project demonstrating MongoDB's $densify aggregation operator for filling gaps in time-series workout data. This project showcases how to use $densify to create continuous date ranges with zero-filled values for missing periods.
It was created as an example solution to a thread in Reddit
- MongoDB aggregation pipeline using
$densifyto fill date gaps - Timezone-aware date handling using
date-fns-tz - Dynamic period grouping (daily, monthly, yearly) based on date range
- Automatic label generation for different time periods
- Workout session aggregation and analysis
- Node.js (v14 or higher)
- MongoDB (v6.0 or higher -
$densifyrequires MongoDB 6.0+) - MongoDB running locally or accessible connection string
- Clone the repository:
git clone <repository-url>
cd mongodb_densify_example- Install dependencies:
npm installThe project connects to MongoDB using the connection string defined in densify.js. By default, it uses:
- Connection URI:
mongodb://localhost:27017/fitness - Database:
Fitness - Collections:
usersandworkouts
To modify the connection, update the MONGODB_URI constant in densify.js:
const MONGODB_URI = 'mongodb://localhost:27017/fitness';Run the script to execute the aggregation pipeline:
node densify.jsThe script will:
- Connect to MongoDB
- Execute the
testWorkouts()aggregation pipeline - Display the results showing workout sessions grouped by time period
- Close the MongoDB connection
The aggregation pipeline performs the following operations:
- Match: Filters users by a specific user ID
- Lookup: Joins workout data from the
workoutscollection - Unwind: Expands the workout array
- Group: Groups workouts by day using
$dateTrunc - Densify: Fills in missing dates in the range (this is the key feature)
- Fill: Sets
totalSessionsto 0 for missing dates - Project: Formats output with appropriate labels based on date range
- Group: Re-groups by period key (day/month/year depending on range)
- Sort: Orders results chronologically
The pipeline adapts its output format based on the number of days:
- ≤ 7 days: Daily view with day names (Mon, Tue, etc.)
- ≤ 90 days: Daily view with date format (YYYY-MM-DD)
- ≤ 365 days: Monthly view (Jan 2024, Feb 2024, etc.)
- > 365 days: Yearly view (2024, 2025, etc.)
- mongoose: ^8.0.0 - MongoDB object modeling
- date-fns: ^3.0.0 - Date utility functions
- date-fns-tz: ^3.2.0 - Timezone support for date-fns
mongodb_densify_example/
├── densify.js # Main script with aggregation pipeline
├── package.json # Project dependencies
├── package-lock.json # Dependency lock file
└── README.md # This file
- The
$densifyoperator requires MongoDB 6.0 or higher - The current implementation uses a hardcoded user ID for testing
- The timezone is set to 'Asia/Kolkata' but can be modified in the
testWorkouts()function - The default date range is 7 days but can be adjusted via the
noOfDaysvariable
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.