Bha*_*avi 7 mongodb pymongo mongodb-query aggregation-framework
我有一个嵌套的嵌入式文档,看起来像这样。每个帖子都有 n 条评论,每条评论都有一个包含姓名和电子邮件 ID 的用户详细信息。
我只想将评论用户的姓名投影到列表中
{
"PostId":"Post001",
"Comments":[
{"_id": "001",
"CommentedBy":{
"_id":"User001",
"Name":"UserName001",
"email":"user001@eg.com"
}
},
{"_id": "002",
"CommentedBy":{
"_id":"User002",
"Name":"UserName002",
"email":"user001@eg.com"
}
},
{"_id": "003",
"CommentedBy":{
"_id":"User003",
"Name":"UserName003",
"email":"user001@eg.com"
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
我想通过使用 mongodb 的聚合管道转换成看起来像这样的东西。
{
"PostId":"Post001"
"Comments":[
{"_id": "001",
"CommentedBy":"UserName001",
},
{"_id": "002",
"CommentedBy": "UserName002"
},
{"_id": "003",
"CommentedBy": "UserName003"
}
]
}
Run Code Online (Sandbox Code Playgroud)
使用 mongo 的投影查询提供了一个CommentedBy包含所有名称的列表。我如何使用 mongo 的聚合查询来实现这一点。有没有办法不使用$unwind.
我试过的查询和我得到的结果。
db.getCollection('post').aggregate([
{$project:{"Comments.CommentedBy":"$Comments.CommentedBy.Name"}}
])
{
"_id" : ObjectId("5b98b4cc3bb8c65aeacabd78"),
"Comments" : [
{
"CommentedBy" : [
"UserName001",
"UserName002",
"UserName003"
]
},
{
"CommentedBy" : [
"UserName001",
"UserName002",
"UserName003"
]
},
{
"CommentedBy" : [
"UserName001",
"UserName002",
"UserName003"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
你可以从计划你想做的事情开始。例如你可以尝试这个:
所以阶段是:
const unwind = {
$unwind: '$Comments',
};
Run Code Online (Sandbox Code Playgroud)
这会导致您的文档重复(或者更确切地说,倍增),数量与您的评论一样多。
现在,根据需要投影评论者姓名/ID:
const project = {
$project: {
PostId: 1,
CommentId: '$Comments._id',
CommentedBy: '$Comments.commentedBy.Name',
},
}
Run Code Online (Sandbox Code Playgroud)
现在,对于每条评论,您都有一个文档:{ PostId, CommentId, CommentedBy }。
现在您可以将您的评论重新分组,按以下方式分组PostId:
const group = {
$group: {
_id: '$PostId',
PostId: '$PostId',
Comments: {
$push: {
_id: '$CommentId',
CommentedBy: '$CommentedBy',
},
},
},
};
Run Code Online (Sandbox Code Playgroud)
您现在将获得如下文件:
{
_id: '<PostID>',
PostId: '<PostID>',
Comments: [
{ _id: '<CommentId>', CommentedBy: '<username>' },
],
}
Run Code Online (Sandbox Code Playgroud)
你会注意到那里有一个额外的顶层_id,你可以在另一个阶段摆脱它$project:
const cleanup = { $project: { _id: 0, ... } };
Run Code Online (Sandbox Code Playgroud)
所以你的整个管道现在很简单:
db.getCollection('posts')
.aggregate([
unwind,
project,
group,
cleanup,
]);
Run Code Online (Sandbox Code Playgroud)
我省略了一些样板文件,并且我在这里没有使用 MongoDB 进行输入,因此您可能需要对代码进行双重和三次检查。(无论如何,您可能想使用来自 internetz 的代码来做到这一点。)
您可以尝试使用$map聚合,并可以通过循环遍历Comments数组来更改内部的键。
db.collection.aggregate([
{ "$project": {
"PostId": 1,
"Comments": {
"$map": {
"input": "$Comments",
"as": "comment",
"in": {
"_id": "$$comment._id",
"CommentedBy": "$$comment.CommentedBy.Name"
}
}
}
}}
])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7911 次 |
| 最近记录: |