Convert date difference to years to calculate age in MongoDB
Update: MongoDB 5.0 solution, will consider leap years as well
db.collection.aggregate([ { $addFields: { age: { $dateDiff: { startDate: "$dob", endDate: "$$NOW", unit: "year" } } } }])
Update: We can just combine the aggregation operators. Note that this solution won't give accurate result as it does not consider leap years
db.getCollection('person').aggregate( [ { $project: { date:"$demographics.DOB", age: { $divide: [{$subtract: [ new Date(), "$Demographics.DOB" ] }, (365 * 24*60*60*1000)] } } } ] )
Old solution with $let
I was able to solve the issue with $let
expression
db.getCollection('person').aggregate( [ { $project: { item: 1, date:"$demographics.DOB", age: { $let:{ vars:{ diff: { $subtract: [ new Date(), "$demographics.DOB" ] } }, in: { $divide: ["$$diff", (365 * 24*60*60*1000)] } } } } } ] )
The accepted answer is incorrect by as many days as there are a leap years that passed since the person was born. Here's a more correct way to calculate age:
{$subtract:[ {$subtract:[{$year:"$$NOW"},{$year:"$dateOfBirth"}]}, {$cond:[ {$gt:[0, {$subtract:[{$dayOfYear:"$$NOW"}, {$dayOfYear:"$dateOfBirth"}]}]}, 1, 0 ]}]}
Starting in Mongo 5.0
, it's a perfect use case for the new $dateDiff
aggregation operator:
// { "dob" : ISODate("1990-03-27") }// { "dob" : ISODate("2008-08-07") }db.collection.aggregate([ { $addFields: { age: { $dateDiff: { startDate: "$dob", endDate: "$$NOW", unit: "year" } } } }])// { "dob" : ISODate("1990-03-27"), "age" : 31 }// { "dob" : ISODate("2008-08-07"), "age" : 13 }
This nicely fits the age scenario since (quoting the documentation) durations produced by $dateDiff
are measured by counting the number of times a unit boundary is passed. For example, two dates that are 18 months apart would return 1 year difference instead of 1.5 years.
Also note that $$NOW
is a variable that returns the current datetime value.