我有以下邮寄文件:
{
"_id" : ObjectId("56960cd909b0d8801d145543"),
"title" : "Post title",
"body" : "Post body"
}
{
"_id" : ObjectId("56960cd909b0d8801d145544"),
"_post": ObjectId("56960cd909b0d8801d145543"),
"body" : "Comment one"
}
{
"_id" : ObjectId("56960cd909b0d8801d145544"),
"_post": ObjectId("56960cd909b0d8801d145543"),
"body" : "Comment Two"
}
正如您从上面的我的文档中看到的,这是我的帖子和评论实现的简单列表(如 SO)。如果帖子有 _post
字段,那么它就是评论,如果没有,那么它就是帖子本身。
当我查询问题56960cd909b0d8801d145543
时,我需要在以下 View 中从 mongoDB 获得响应:
// query
Post.aggregate({_id: ObjectId("56960cd909b0d8801d145543")});
// result
{
"_id" : ObjectId("56960cd909b0d8801d145543"),
"title" : "Post title",
"body" : "Post body",
"comments" [{
"_id" : ObjectId("56960cd909b0d8801d145544"),
"_post": ObjectId("56960cd909b0d8801d145543"),
"body" : "Comment one"
},
{
"_id" : ObjectId("56960cd909b0d8801d145544"),
"_post": ObjectId("56960cd909b0d8801d145543"),
"body" : "Comment Two"
}]
}
我应该如何构建聚合管道以获得上面的结果?
最佳答案
以下管道应该适合您:
var pipeline = [
{
"$project": {
"title": 1, "body": 1,
"post_id": { "$ifNull": [ "$_post", "$_id" ] }
}
},
{
"$group": {
"_id": "$post_id",
"title": { "$first": "$title" },
"body": { "$first": "$body" },
"comments": {
"$push": {
"_id": "$_id",
"_post": "$post_id",
"body": "$body"
}
}
}
},
{
"$project": {
"title": 1, "body": 1,
"comments": {
"$setDifference": [
{
"$map": {
"input": "$comments",
"as": "el",
"in": {
"$cond": [
{ "$ne": [ "$$el._id", "$$el._post" ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
];
Post.aggregate(pipeline, function (err, result) {
if (err) { /* handle error */ };
console.log(result);
});
管道的结构方式使得您的第一步, $project
算子阶段,就是投影领域post_id
在下一个管道阶段用作按键分组。由于您的架构是分层的,因此您需要此字段作为父/根文档。 $ifNull
运算符将充当合并运算符,如果文档中不存在该字段,则返回替换值。
下一个管道步骤, $group
管道阶段尝试对数据进行分组来处理它们。 $group
管道运算符类似于 SQL 的 GROUP BY 子句。在 SQL 中,除非使用任何聚合函数,否则我们不能使用 GROUP BY。同样,我们也必须在 MongoDB 中使用聚合函数。在这种情况下,您需要 $push
运算符来创建评论数组。然后使用 $first
累积其他字段。 运算符。
最后一步涉及调整评论数组,以便删除包含帖子详细信息的文档,这绝对不是评论类型。这是通过 $setDifference
实现的。 和 $map
运营商。 $map
运算符本质上创建一个新的数组字段,该字段保存数组每个元素的子表达式中计算逻辑的结果值。 $setDifference
运算符然后返回一个集合,其中包含出现在第一个集合中但未出现在第二个集合中的元素;即执行第二组相对于第一组的相对补充。在这种情况下,它将返回最终的 comments
包含与父文档不相关的元素的数组 _id
属性。
关于mongodb - 如何使用 MongoDB 聚合框架对嵌套帖子进行分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34762343/