Raf*_*nte 5 mongoose mongodb node.js aggregation-framework
我有一个简单的数据库布局,如下所示:
client
id
sex (male/female)
birthday (date)
client
id
sex (male/female)
birthday (date)
(...)
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个汇总命令,输出我有多少男性和女性客户,我也想输出男性和女性的平均年龄,不确定我是否可以在同一个命令中执行此操作或我需要2个独立的?
// Count of males/females, average age
Clients.aggregate({
$project : {"sex" : 1,
"sexCount" : 1,
"birthday" : 1,
"avgAge" : 1
}
},
{
$match: {"sex": {$exists: true}}
},
{
$group: {
_id : "$sex",
sexCount : { $sum: 1 },
avgAge : { $avg: "$birthday" },
}
},
{ $sort: { _id: 1 } }
, function(err, sex_dbres) {
if (err)
throw err;
else{
(...)
}
});
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,我得到男性/女性的数量,但avgAge为0.任何想法?
非常感谢
如果您将年龄存储在原始文档中,答案会更简单(正如Dmitry发布的那样,您可以直接avgAge:{$avg:"$age"}在您的$group步骤中执行.
聚合框架非常漂亮,并且有许多很酷的运算符,允许您"动态"计算这个丢失的年龄字段.
我将把聚合的每一步存储在一个变量中,这样就可以更容易地看到发生了什么:
today = new Date();
// split today and bday into numerical year and numerical day-of-the-year
project1= {
"$project" : {
"sex" : 1,
"todayYear" : {
"$year" : today
},
"todayDay" : {
"$dayOfYear" : today
},
"by" : {
"$year" : "$bday"
},
"bd" : {
"$dayOfYear" : "$bday"
}
}
};
// calculate age in days by subtracting bday in days from today in days
project2 = {
"$project" : {
"sex" : 1,
"age" : {
"$subtract" : [
{
"$add" : [
{
"$multiply" : [
"$todayYear",
365
]
},
"$todayDay"
]
},
{
"$add" : [
{
"$multiply" : [
"$by",
365
]
},
"$bd"
]
}
]
}
}
};
// sum up for each sex the count and compute avg age (in days)
group = {
"$group" : {
"_id" : "$sex",
"total" : {
"$sum" : 1
},
"avgAge" : {
"$avg" : "$age"
}
}
};
// divide days by 365 to get age in years.
project3 = {
"$project" : {
"_id" : 0,
"sex" : "$_id",
"total" : 1,
"averageAge" : {
"$divide" : [
"$avgAge",
365
]
}
}
};
Run Code Online (Sandbox Code Playgroud)
现在您可以运行聚合:
> db.client.find({},{_id:0})
{ "sex" : "male", "bday" : ISODate("2000-02-02T08:00:00Z") }
{ "sex" : "male", "bday" : ISODate("1987-02-02T08:00:00Z") }
{ "sex" : "female", "bday" : ISODate("1989-02-02T08:00:00Z") }
{ "sex" : "female", "bday" : ISODate("1993-11-02T08:00:00Z") }
> db.client.aggregate([ project1, project2, group, project3 ])
{
"result" : [
{
"sex" : "female",
"total" : 2,
"averageAge" : 21.34109589041096
},
{
"sex" : "male",
"total" : 2,
"averageAge" : 19.215068493150685
}
],
"ok" : 1
}
>
Run Code Online (Sandbox Code Playgroud)
这不简单的原因是目前Aggregation Framework不支持直接减去日期.请投票给https://jira.mongodb.org/browse/SERVER-6239,它是针对下一个主要版本的目标 - 一旦实现它应该允许直接减去日期(尽管你仍然需要将其转换为适当的粒度,在这种情况下可能是几年).
小智 4
日期对象无法“平均”,但数字可以。您可以将日期转换为时间戳值,然后从中查找平均值。但这仍然不是平均年龄,您需要从聚合函数之外的当前日期中减去结果。
另一种选择是假设可以仅使用日期的年份部分来计算年龄(也就是说,如果我出生于 2000 年 12 月 1 日,在今天的报告中我将是 12 岁,而不是 11 岁)。在这种情况下,您可以使用日期运算符来提取年份值。
$project : {"sex" : 1,
"sexCount" : 1,
"year" : {$year: "$birthday"},
}
},
$project : {"sex" : 1,
"sexCount" : 1,
"age" : {$subtract: [2012, '$year']},
}
},
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7348 次 |
| 最近记录: |