How to use MongoDB date aggregation operators in Node.js with Mongoose ($dayOfMonth, $dayOfYear, $dayOfWeek, etc)
While I was working on creating a tutorial for MongoDB aggregation I came across a few issues while trying to use the built in date aggregation operators. I was storing the date in the db as the unix epoch timestamp. I tried multiple variations such as “new Date()”, “new Date().getTime()”, “Date.now()”, etc, but none of those would work. I kept getting this error “can’t convert from BSON type NumberDouble to Date”. Turns out, the solution was very simple, and something I completely overlooked
The MongoDB date aggregation operators are designed to work on BSON date/time data type, a 64-bit int storing the number of UTC milliseconds from unix epoch. In order to use these operators there are a few things you should keep in mind when designing your application and setting everything up.
MongoDB Schema Requirements
One thing that I overlooked was the database schema I had already setup. My original setup in the database schema had the key type set as number…this will not work, and will normally be the cause of why you see the “can’t convert from BSON type NumberDouble to Date” error.
When defining the database schema you must use:
1 2 3 |
var orderSchema = new Schema({ date_created: { type: Date, default: Date.now } }) |
Notice above how we set in the schema to use the Date type instead of Number, String, etc. You need to use this type as there isn’t any way (at least that I know of) to convert the number to a date inside the MongoDB aggregation framework. When you set it as a date Type, instead of just storing the value, it will store like this in the MongoDB database:
1 |
date_created: new Date("Mon, 14 Oct 2013 15:06:15 GMT") |
Instead of:
1 |
date_created: "Mon, 14 Oct 2013 15:06:15 GMT" |
If you used Number type and set it with epoch milliseconds time, it would be a number instead of date string. Either way, as you can see it is stored in the database as a date object.
Set and store value using Node.js
Now that the schema has been defined as a Date type it will be stored as a date object, we just need to save it using Node.js like so:
1 2 3 4 |
var Orders = mongoose.model('Orders', orderSchema); var newOrder = new Orders; newOrder.date_created = Date.now(); newOrder.save(callback); |
Using MongoDB aggregation date operators (with Mongoose)
Now that we have our Schema set correctly, and stored the date as a date object in the database, we can use any of the MongoDB aggregation date operators as needed:
1 |
Orders.aggregate({ $project: { day: { $dayOfMonth: "$date_created" } } }); |
You can use the date operators inside any of the MongoDB Pipeline Operators. Check out this page for more information:
http://docs.mongodb.org/manual/reference/operator/aggregation/
You’ve now learned how to use the MongoDB Aggregation Date Operators, congrats!
Available MongoDB Aggregation Date Operators
Date operators take a “Date” typed value as a single argument and return
a number.
Name | Description |
---|---|
$dayOfYear | Converts a date to a number between 1 and 366. |
$dayOfMonth | Converts a date to a number between 1 and 31. |
$dayOfWeek | Converts a date to a number between 1 and 7. |
$year | Converts a date to the full year. |
$month | Converts a date into a number between 1 and 12. |
$week | Converts a date into a number between 0 and 53 |
$hour | Converts a date into a number between 0 and 23. |
$minute | Converts a date into a number between 0 and 59. |
$second | Converts a date into a number between 0 and 59. May be 60 to account for leap seconds. |
$millisecond | Returns the millisecond portion of a date as an integer between 0 and 999. |
-
Ryan
-
Myles
-
JuanJo
-
-
uniquate
-
uniquate
-
Myles
-