您需要使用聚合框架,在其中运行聚合管道,该管道具有 $group 运算符管道阶段,该阶段聚合文档以使用累加器运算符创建所需的计数 $sum。
为了获得所需的结果,您需要使用像 $cond 这样的三元运算符来创建独立的计数字段,因为这会将文档数提供给 $sum 表达式取决于名称值。 $cond 运算符可以有效地用于根据reply 字段值评估计数。它将逻辑条件作为其第一个参数 (if),然后返回计算结果为 true (then) 的第二个参数或返回 false (else) 的第三个参数。这会将 true/false 布尔计算的返回值转换为 1 和 0,它们将分别输入 $sum:
"$cond": [
{ "$eq": ["$reply", ">"] },
1, 0
]
因此,如果在正在处理的文档中 "$reply" 字段具有 ">" 值,则 $cond 运算符会将值 1 提供给 $sum 否则它的总和为零。
使用 $project 作为您的最后一个管道步骤,因为它允许您重塑流中的每个文档,包括、排除或重命名字段,注入计算字段,创建子文档字段,使用数学表达式、日期、字符串和/或逻辑(比较、布尔、控制)表达式。它类似于 SQL 中的SELECT。
以下管道应返回所需的结果:
Model.aggregate([
{
"$group": {
"_id": "$criterion",
">": {
"$sum": {
"$cond": [
{ "$eq": [ "$reply", ">" ] },
1, 0
]
}
},
"<": {
"$sum": {
"$cond": [
{ "$eq": [ "$reply", "<" ] },
1, 0
]
}
}
}
},
{
"$project": {
"_id": 0,
"criterion": "$_id",
"result.>": "$>",
"result.<": "$<"
}
}
]).exec(function(err, result) {
console.log(JSON.stringify(result, null, 4));
});
控制台输出示例
{
"criterion" : "story",
"result" : {
">" : 1,
"<" : 2
}
}
注意:这种方法考虑到$reply 字段的值是固定且已知的,因此在值是动态且未知的情况下它不灵活。
对于一个比上述执行速度更快、性能更好并且还考虑到计数字段的未知值的更灵活的替代方案,我建议按如下方式运行管道:
Model.aggregate([
{
"$group": {
"_id": {
"criterion": "$criterion",
"reply": "$reply"
},
"count": { "$sum": 1 }
}
},
{
"$group": {
"_id": "$_id.criterion",
"result": {
"$push": {
"reply": "$_id.reply",
"count": "$count"
}
}
}
}
]).exec(function(err, result) {
console.log(JSON.stringify(result, null, 4));
});
控制台输出示例
{
"_id" : "story",
"result" : [
{
"reply" : "<",
"count" : 2
},
{
"reply" : ">",
"count" : 1
}
]
}