mongodb 中的条件聚合函数
condtitional aggregate function in mongodb
我有一个 mongodb 的数据为
{
"_id": "a",
"reply": "<",
"criterion": "story"
},
{
"_id": "b",
"reply": "<",
"criterion": "story"
},
{
"_id": "c",
"reply": ">",
"criterion": "story"
}
我想要的结果是:
{
"criterion": "story",
"result" : {
">" : 1,
"<" : 2
}
}
我想在 "criterion" 上汇总。因此,如果我这样做,将有 1 个文件。但是,我想计算“<”和“>”的数量,并将其写入上面 json 所示的新密钥中。这就是这背后的逻辑。 mongodb 有好主意的人可以帮我解决这个问题吗?
您需要使用聚合框架,您将 运行 具有 $group
operator pipeline stage which aggregates the documents to create the desired counts using the accumulator operator $sum
的聚合管道。
为了获得所需的结果,您需要分别使用像 $cond
to create the independent count fields since that will feed the number of documents to the $sum
expression depending on the name value. The $cond
operator can be used effectively to evaluate the counts based on the reply
field value. It takes a logical condition as its first argument (if) and then returns the second argument where the evaluation is true (then) or the third argument where false (else). This converts the true/false
boolean evaluated returns into 1 and 0 that will feed into $sum
这样的三元运算符:
"$cond": [
{ "$eq": ["$reply", ">"] },
1, 0
]
因此,如果在正在处理的文档中 "$reply"
字段具有 ">"
值,则 $cond
operator feeds the value 1 to the $sum
否则它的总和为零值。
使用 $project
作为最后的管道步骤,因为它允许您重塑流中的每个文档,包括、排除或重命名字段,注入计算字段,创建子文档字段,使用数学表达式、日期、字符串 and/or 逻辑(比较、布尔、控制)表达式。类似于SQL中的SELECT
。
以下管道应该 return 期望的结果:
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
}
]
}
我有一个 mongodb 的数据为
{
"_id": "a",
"reply": "<",
"criterion": "story"
},
{
"_id": "b",
"reply": "<",
"criterion": "story"
},
{
"_id": "c",
"reply": ">",
"criterion": "story"
}
我想要的结果是:
{
"criterion": "story",
"result" : {
">" : 1,
"<" : 2
}
}
我想在 "criterion" 上汇总。因此,如果我这样做,将有 1 个文件。但是,我想计算“<”和“>”的数量,并将其写入上面 json 所示的新密钥中。这就是这背后的逻辑。 mongodb 有好主意的人可以帮我解决这个问题吗?
您需要使用聚合框架,您将 运行 具有 $group
operator pipeline stage which aggregates the documents to create the desired counts using the accumulator operator $sum
的聚合管道。
为了获得所需的结果,您需要分别使用像 $cond
to create the independent count fields since that will feed the number of documents to the $sum
expression depending on the name value. The $cond
operator can be used effectively to evaluate the counts based on the reply
field value. It takes a logical condition as its first argument (if) and then returns the second argument where the evaluation is true (then) or the third argument where false (else). This converts the true/false
boolean evaluated returns into 1 and 0 that will feed into $sum
这样的三元运算符:
"$cond": [
{ "$eq": ["$reply", ">"] },
1, 0
]
因此,如果在正在处理的文档中 "$reply"
字段具有 ">"
值,则 $cond
operator feeds the value 1 to the $sum
否则它的总和为零值。
使用 $project
作为最后的管道步骤,因为它允许您重塑流中的每个文档,包括、排除或重命名字段,注入计算字段,创建子文档字段,使用数学表达式、日期、字符串 and/or 逻辑(比较、布尔、控制)表达式。类似于SQL中的SELECT
。
以下管道应该 return 期望的结果:
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
}
]
}