我在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从用户表中查找所有作者数据。
现在是我的代码:
{
"$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:不支持聚合项目运算符:'$ 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:聚合项目操作员未支持:“ $ push”
这是因为您有嵌套的$push
。如果您在mongo shell中输入了此聚合管道,则应该在下面收到错误消息:
"errmsg": "Unrecognized expression '$push'",
这是因为嵌套操作应该是aggregation expression,但是$push
不是表达式运算符。
我需要在MongoDB查询中进行哪些更改?
在$group之后使用$unwind实际上是一些反模式。我建议使用$map和$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
步骤两次来倒回嵌套数组。希望这对将来偶然遇到类似需求的人有所帮助。