Reputation: 4328
I have a field in my MongoDB collection products
called date_expired
.
It's of type: date
and stores the a date string.
I want to retrieve all the products and change the date_expired
property in the result to number of hours left from now. How do I do this?
It's similar to getter()
in Laravel...?
Upvotes: 1
Views: 1556
Reputation: 203304
You could create a virtual property that will return the number of hours until expiry:
ProductSchema.virtual('hoursToExpiry').get(function() {
return (this.date_expired - Date.now()) / 3600000;
});
To access this property:
console.log('hours to expiry:', doc.hoursToExpiry)
If you want to include that property in any JSON or JS object, make sure that you set virtuals : true
:
console.log('%j', doc.toJSON({ virtuals : true }));
Upvotes: 3
Reputation: 103365
Would consider using the aggregation framework in this case to output the transformation. You can use the $project
pipeline arithmetic operators $divide
and $subtract
to achieve the final goal. These will enable you to carry out the arithmetic of calculating the number of hours to expiry i.e. implement the formula:
hoursToExpiry = (date_expired - timeNow)/1000*60*60 //the time units are all in milliseconds
Take for instance the following short mongo shell demo that will strive to drive home this concept:
Populate test collection:
db.test.insert([
{
"date_expired": ISODate("2016-03-27T10:55:13.069Z"),
"name": "foo"
},
{
"date_expired": ISODate("2016-06-11T20:55:13.069Z"),
"name": "bar"
},
{
"date_expired": ISODate("2016-06-11T16:17:23.069Z"),
"name": "buzz"
}
])
Aggregation Operation:
db.test.aggregate([
{
"$project": {
"name": 1,
"dateExpired": "$date_expired",
"dateNow": { "$literal": new Date() },
"hoursToExpiry": {
"$divide": [
{ "$subtract": [ "$date_expired", new Date() ] },
1000*60*60
]
}
}
}
])
Result (at the time of writing):
{
"result" : [
{
"_id" : ObjectId("575c0f6e8101b29fc93e5b9d"),
"name" : "foo",
"dateExpired" : ISODate("2016-03-27T10:55:13.069Z"),
"dateNow" : ISODate("2016-06-11T13:36:21.025Z"),
"hoursToExpiry" : -1826.685543333333
},
{
"_id" : ObjectId("575c0f6e8101b29fc93e5b9e"),
"name" : "bar",
"dateExpired" : ISODate("2016-06-11T20:55:13.069Z"),
"dateNow" : ISODate("2016-06-11T13:36:21.025Z"),
"hoursToExpiry" : 7.314456666666667
},
{
"_id" : ObjectId("575c0f6e8101b29fc93e5b9f"),
"name" : "buzz",
"dateExpired" : ISODate("2016-06-11T16:17:23.069Z"),
"dateNow" : ISODate("2016-06-11T13:36:21.025Z"),
"hoursToExpiry" : 2.683901111111111
}
],
"ok" : 1
}
With the above pipeline, you can then adopt it to your Mongoose implementation with the aggregate()
method as basis of your query:
Product.aggregate([
{
"$project": {
"name": 1,
"dateExpired": "$date_expired",
"dateNow": { "$literal": new Date() },
"hoursToExpiry": {
"$divide": [
{ "$subtract": [ "$date_expired", new Date() ] },
1000*60*60
]
}
}
}
]).exec(function (err, result) {
// Handle err
console.log(result);
});
or using the more affluent API:
Product.aggregate()
.project({
"name": 1,
"dateExpired": "$date_expired",
"dateNow": { "$literal": new Date() },
"hoursToExpiry": {
"$divide": [
{ "$subtract": [ "$date_expired", new Date() ] },
1000*60*60
]
}
})
.exec(function (err, result) {
// Handle err
console.log(result);
});
Upvotes: 1