展开两次后倒回两次
Rewind twice after unwinding twice
我在 MongoDB 中有一份文件,我正在尝试展开它。我想展开带有 comments
字段的文档,然后展开每个评论中的 replies
字段。之后我需要把它倒回去。
所以文档结构是这样的:
{
"_id": <some_id>,
"post_body": "test post",
"author_id": <some_user_id>,
"comments": [
{
"comment_body": "comment test",
"comment_author_id": <some_user_id>,
"replies": [
{
"reply_body": "reply test",
"reply_author_id": <some_user_id>
},
... more items
]
},
... more items
]
}
我也在尝试使用附加的已保存 ID 从用户 table 查找所有作者数据。
这是我现在的代码:
{
"$match": {"post_id": post_id}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "author_id",
"foreignField": "_id",
"as": "author_data"
}
},
{
"$unwind": {
"path": "$comments",
"preserveNullAndEmptyArrays": True
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.comment_author_id",
"foreignField": "_id",
"as": "comment_author_data"
}
},
{
"$unwind": {
"path": "$comments.replies",
"preserveNullAndEmptyArrays": True
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.replies.reply_author_id",
"foreignField": "_id",
"as": "reply_author_data"
}
},
{
"$group": {
"_id": '$_id',
"post_body": {"$first": "$post_body"},
"author": {"$first": "$authorData"},
"comments": {
"$push": {
"comment_body": "$comments.comment_body",
"comment_author_data": "$comment_author_data",
"replies": {
"$push": {
"reply_body": "$comments.replies.reply_body",
"reply_author_data": "$reply_author_data"
}
}
}
}
}
}
我收到这个错误
pymongo.errors.OperationFailure: Aggregation project operator not supported: '$push'
我想得到:
{
"_id": <some_id>,
"post_body": "test post",
"author_data": {"author_name": "test1"},
"comments": [
{
"comment_body": "comment test",
"comment_author_data": {"author_name": "test1"},
"replies": [
{
"reply_body": "reply test",
"reply_author_data": {"author_name": "test1"}
},
... more items
]
},
... more items
]
}
我的 MongoDB 查询需要更改什么?
pymongo.errors.OperationFailure: Aggregation project operator not
supported: '$push'
这是因为您有一个嵌套的 $push
。如果您在 mongo shell 中输入此聚合管道,您应该会收到以下错误消息:
"errmsg": "Unrecognized expression '$push'",
这是因为嵌套运算应该是 aggregation expression,但 $push
不是表达式运算符。
What do I need to change in my MongoDB query?
使用$group after $unwind is actually a bit of anti-pattern. I'd recommend using $map and $reduce。例如:
db.collection.aggregate([
{
"$lookup": {
"from": "usersLookup",
"localField": "author_id",
"foreignField": "_id",
"as": "author_data"
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.comment_author_id",
"foreignField": "_id",
"as": "comment_author_data"
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.replies.reply_author_id",
"foreignField": "_id",
"as": "reply_author_data"
}
},
{"$addFields": {
"author_data": {
"$reduce": {
"input":"$author_data",
"initialValue": "",
"in": "$$this"
}
},
"comments": {
"$map": {
"input": "$comments",
"as": "c",
"in": {
"comment_author_id": "$$c.comment_author_id",
"comment_body": "$$c.comment_body",
"comment_author_data": {
"$arrayElemAt": [
"$comment_author_data",
{ "$indexOfArray": [ "$comment_author_data._id", "$$c.comment_author_id" ] }
]
},
"replies": {
"$map":{
"input": "$$c.replies",
"as": "r",
"in":{
"reply_body":"$$r.reply_body",
"reply_author_id":"$$r.reply_author_id",
"reply_author_data":{
"$arrayElemAt": [
"$reply_author_data",
{"$indexOfArray": ["$reply_author_data._id", "$$r.reply_author_id"] }
]
}
}
}
}
}
}
},
}},
{"$project": {
"author_data._id":0,
"comment_author_data":0,
"comments.comment_author_data._id":0,
"reply_author_data":0,
"comments.replies.reply_author_data._id":0
}}
])
上面应该解析来自 $lookup 的嵌套数组结果,而不使用 $unwind
和 $group
。上面的聚合管道示例是在 MongoDB v4.2.
中编写的
经过数小时的代码乱写,我得到了这段代码,它给出了我需要的结果。
[
{
"$match":{
"post_id":"post_id"
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"author_id",
"foreignField":"_id",
"as":"author_data"
}
},
{
"$unwind":{
"path":"$comments",
"preserveNullAndEmptyArrays":True
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"comments.comment_author_id",
"foreignField":"_id",
"as":"comment_author_data"
}
},
{
"$unwind":{
"path":"$comments.replies",
"preserveNullAndEmptyArrays":True
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"comments.replies.reply_author_id",
"foreignField":"_id",
"as":"reply_author_data"
}
},
{
"$group":{
"_id":{
"_id":"$_id",
"author":"$author_data",
"post_body":"$post_body",
"comment_body":"$comments.comment_body",
"comment_author_data":"$comment_author_data"
},
"replies":{
"$push":{
"reply_body":"$comments.replies.reply_body",
"reply_author_data":"$reply_author_data"
}
}
}
},
{
"$group":{
"_id":"$_id._id",
"post_body":{
"$first":"$_id.post_body"
},
"author_data":{
"$first":"$_id.author"
},
"comments":{
"$push":{
"comment_body":"$_id.comment_body",
"comment_author_data":"$_id.comment_author_data",
"replies":"$replies"
}
}
}
}
]
我不得不使用 $group
步两次来倒回嵌套数组。希望这对以后遇到类似需求的任何人有所帮助。
我在 MongoDB 中有一份文件,我正在尝试展开它。我想展开带有 comments
字段的文档,然后展开每个评论中的 replies
字段。之后我需要把它倒回去。
所以文档结构是这样的:
{
"_id": <some_id>,
"post_body": "test post",
"author_id": <some_user_id>,
"comments": [
{
"comment_body": "comment test",
"comment_author_id": <some_user_id>,
"replies": [
{
"reply_body": "reply test",
"reply_author_id": <some_user_id>
},
... more items
]
},
... more items
]
}
我也在尝试使用附加的已保存 ID 从用户 table 查找所有作者数据。
这是我现在的代码:
{
"$match": {"post_id": post_id}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "author_id",
"foreignField": "_id",
"as": "author_data"
}
},
{
"$unwind": {
"path": "$comments",
"preserveNullAndEmptyArrays": True
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.comment_author_id",
"foreignField": "_id",
"as": "comment_author_data"
}
},
{
"$unwind": {
"path": "$comments.replies",
"preserveNullAndEmptyArrays": True
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.replies.reply_author_id",
"foreignField": "_id",
"as": "reply_author_data"
}
},
{
"$group": {
"_id": '$_id',
"post_body": {"$first": "$post_body"},
"author": {"$first": "$authorData"},
"comments": {
"$push": {
"comment_body": "$comments.comment_body",
"comment_author_data": "$comment_author_data",
"replies": {
"$push": {
"reply_body": "$comments.replies.reply_body",
"reply_author_data": "$reply_author_data"
}
}
}
}
}
}
我收到这个错误
pymongo.errors.OperationFailure: Aggregation project operator not supported: '$push'
我想得到:
{
"_id": <some_id>,
"post_body": "test post",
"author_data": {"author_name": "test1"},
"comments": [
{
"comment_body": "comment test",
"comment_author_data": {"author_name": "test1"},
"replies": [
{
"reply_body": "reply test",
"reply_author_data": {"author_name": "test1"}
},
... more items
]
},
... more items
]
}
我的 MongoDB 查询需要更改什么?
pymongo.errors.OperationFailure: Aggregation project operator not supported: '$push'
这是因为您有一个嵌套的 $push
。如果您在 mongo shell 中输入此聚合管道,您应该会收到以下错误消息:
"errmsg": "Unrecognized expression '$push'",
这是因为嵌套运算应该是 aggregation expression,但 $push
不是表达式运算符。
What do I need to change in my MongoDB query?
使用$group after $unwind is actually a bit of anti-pattern. I'd recommend using $map and $reduce。例如:
db.collection.aggregate([
{
"$lookup": {
"from": "usersLookup",
"localField": "author_id",
"foreignField": "_id",
"as": "author_data"
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.comment_author_id",
"foreignField": "_id",
"as": "comment_author_data"
}
},
{
"$lookup": {
"from": "usersLookup",
"localField": "comments.replies.reply_author_id",
"foreignField": "_id",
"as": "reply_author_data"
}
},
{"$addFields": {
"author_data": {
"$reduce": {
"input":"$author_data",
"initialValue": "",
"in": "$$this"
}
},
"comments": {
"$map": {
"input": "$comments",
"as": "c",
"in": {
"comment_author_id": "$$c.comment_author_id",
"comment_body": "$$c.comment_body",
"comment_author_data": {
"$arrayElemAt": [
"$comment_author_data",
{ "$indexOfArray": [ "$comment_author_data._id", "$$c.comment_author_id" ] }
]
},
"replies": {
"$map":{
"input": "$$c.replies",
"as": "r",
"in":{
"reply_body":"$$r.reply_body",
"reply_author_id":"$$r.reply_author_id",
"reply_author_data":{
"$arrayElemAt": [
"$reply_author_data",
{"$indexOfArray": ["$reply_author_data._id", "$$r.reply_author_id"] }
]
}
}
}
}
}
}
},
}},
{"$project": {
"author_data._id":0,
"comment_author_data":0,
"comments.comment_author_data._id":0,
"reply_author_data":0,
"comments.replies.reply_author_data._id":0
}}
])
上面应该解析来自 $lookup 的嵌套数组结果,而不使用 $unwind
和 $group
。上面的聚合管道示例是在 MongoDB v4.2.
经过数小时的代码乱写,我得到了这段代码,它给出了我需要的结果。
[
{
"$match":{
"post_id":"post_id"
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"author_id",
"foreignField":"_id",
"as":"author_data"
}
},
{
"$unwind":{
"path":"$comments",
"preserveNullAndEmptyArrays":True
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"comments.comment_author_id",
"foreignField":"_id",
"as":"comment_author_data"
}
},
{
"$unwind":{
"path":"$comments.replies",
"preserveNullAndEmptyArrays":True
}
},
{
"$lookup":{
"from":"usersLookup",
"localField":"comments.replies.reply_author_id",
"foreignField":"_id",
"as":"reply_author_data"
}
},
{
"$group":{
"_id":{
"_id":"$_id",
"author":"$author_data",
"post_body":"$post_body",
"comment_body":"$comments.comment_body",
"comment_author_data":"$comment_author_data"
},
"replies":{
"$push":{
"reply_body":"$comments.replies.reply_body",
"reply_author_data":"$reply_author_data"
}
}
}
},
{
"$group":{
"_id":"$_id._id",
"post_body":{
"$first":"$_id.post_body"
},
"author_data":{
"$first":"$_id.author"
},
"comments":{
"$push":{
"comment_body":"$_id.comment_body",
"comment_author_data":"$_id.comment_author_data",
"replies":"$replies"
}
}
}
}
]
我不得不使用 $group
步两次来倒回嵌套数组。希望这对以后遇到类似需求的任何人有所帮助。