6

我有一个存储在 mongo 中的用户群。用户可以记录他们的出生日期。我需要运行一个按年龄聚合用户的报告。

我现在有一个按出生年份对用户进行分组的管道。但是,这还不够精确,因为大多数人不是在 1 月 1 日出生的;因此,即使他们出生于 1970 年,也可能还不到 43 岁。

db.Users.aggregate([
    { $match : { "DateOfBirth" : { $exists : true} } },
    { $project : {"YearOfBirth" : {$year : "$DateOfBirth"} } }, 
    { $group : { _id : "$YearOfBirth", Total : { $sum : 1} } },
    { $sort : { "Total" : -1 } }
])

你知道是否可以在聚合框架内执行某种算术来准确计算用户的年龄?还是仅使用 MapReduce 可以做到这一点?

4

2 回答 2

9

似乎在刚刚发布的新 Mongo 2.4 版本中,整个事情都是可能的,支持额外的 Date 操作(即“$subtract”)。

我是这样做的:

db.Users.aggregate([
    { $match : { "DateOfBirth" : { $exists : true} } },
    { $project : {"ageInMillis" : {$subtract : [new Date(), "$DateOfBirth"] } } }, 
    { $project : {"age" : {$divide : ["$ageInMillis", 31558464000] }}},
    // take the floor of the previous number:
    { $project : {"age" : {$subtract : ["$age", {$mod : ["$age",1]}]}}},
    { $group : { _id : "$age", Total : { $sum : 1} } },
    { $sort : { "Total" : -1 } }
])
于 2013-03-22T16:34:54.810 回答
1

没有足够的 dateTime 运算符和数学运算符来预测日期。但是您也许可以通过编写动态查询来创建年龄范围:

将您的日期范围定义为截止日期

dt18 = 今天 - 18 dt25 = 今天 - 25 ... dt65 = 今天 - 65

然后执行嵌套条件,逐步使用截止日期作为年龄组标记,如下所示:

db.folks.save({ "_id" : 1, "bd" : ISODate("2000-02-03T00:00:00Z") });
db.folks.save({ "_id" : 2, "bd" : ISODate("2010-06-07T00:00:00Z") });
db.folks.save({ "_id" : 3, "bd" : ISODate("1990-10-20T00:00:00Z") });
db.folks.save({ "_id" : 4, "bd" : ISODate("1964-09-23T00:00:00Z") });


db.folks.aggregate(
    {
    $project: {
        ageGroup: {
            $cond: [{
                $gt: ["$bd",
                ISODate("1995-03-19")]
            },
            "age0_18",
            {
                $cond: [{
                    $gt: ["$bd",
                    ISODate("1988-03-19")]
                },
                "age18_25",
                "age25_plus"]
            }]
        }
    }
},
{
    $group: {
        _id: "$ageGroup",
        count: {
            $sum: 1
        }
    }
})
于 2013-03-19T17:45:00.683 回答