展开两次后倒回两次

问题描述 投票:1回答:2

我在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查询中进行哪些更改?

python pymongo aws-documentdb
2个回答
1
投票

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编写的。


0
投票

经过数小时的代码编写,我找到了该代码,它为我提供了所需的结果。

[
   {
      "$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步骤两次来倒回嵌套数组。希望这对将来偶然遇到类似需求的人有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.