在 MongoDB 中使用嵌套数组查找

Stucking with nested array lookup in MongoDB

我正在尝试从 mongodb 中的嵌套数组查找查询,但遇到问题。

我总共有三个 collections。 (1) 频道 (Parent) (2) 通道线程 (Children) (3) 用户

频道Collection:

{
    "_id" : ObjectId("61efcbdc1aa27f83da47c93f"),
    "tags" : [],
    "slug_history" : [ 
        "iny1Xik"
    ],
    "title" : "Pirate Chat",
    "settingId" : ObjectId("61408586b719c8ce89f08674"),
    "status" : "published",
    "lockedPageContent" : "",
    "slug" : "iny1Xik",
    "createdAt" : ISODate("2022-01-25T10:07:24.144Z"),
    "updatedAt" : ISODate("2022-01-25T10:07:24.144Z"),
    "__v" : 0
}

频道话题Collection:

{
    "_id" : ObjectId("61efcd5df82318884746eb80"),
    "threadImage" : [],
    "parentId" : null,
    "channelId" : ObjectId("61efcbdc1aa27f83da47c93f"),
    "authorId" : ObjectId("6177de8f8a5fd72a4f37b7db"),
    "threadText" : "New Message",
    "reactions" : [ 
        {
            "authors" : [ 
                ObjectId("3687de8f8a5fd72a4f37b7bg")
            ],
            "_id" : ObjectId("61ef856432753c196382c37d"),
            "icon" : "&#128528"
        }
    ],
    "createdAt" : ISODate("2022-01-25T10:13:49.033Z"),
    "updatedAt" : ISODate("2022-01-25T10:13:49.033Z"),
    "__v" : 0
}

用户Collection:

{
    "_id" : ObjectId("6177de8f8a5fd72a4f37b7db"),
    "image" : "",
    "tags" : [],
    "pushTokens" : [],
    "lastLogin" : ISODate("2022-01-25T10:08:19.055Z"),
    "firstName" : "dinesh",
    "lastName" : "patel",
    "email" : "dineshpatel@example.com",
    "infusionSoftId" : "784589",
    "role" : "user",
    "__v" : 0,
    "settings" : {
        "commentNotification" : false,
        "commentReplyNotification" : true
    }
}

我正在尝试查找线程反应的作者。

预期输出:

{
    "_id": ObjectId("61efcbdc1aa27f83da47c93f"),
    "tags": [],
    "slug_history": [
        "iny1Xik"
    ],
    "title": "Pirate Chat",
    "settingId": ObjectId("61408586b719c8ce89f08674"),
    "status": "published",
    "lockedPageContent": "",
    "slug": "iny1Xik",
    "createdAt": ISODate("2022-01-25T10:07:24.144Z"),
    "updatedAt": ISODate("2022-01-25T10:07:24.144Z"),
    "__v": 0,
    "threads": [
        {
            "_id": ObjectId("61efcd5df82318884746eb80"),
            "threadImage": [],
            "parentId": null,
            "channelId": ObjectId("61efcbdc1aa27f83da47c93f"),
            "authorId": {
                "_id": ObjectId("6177de8f8a5fd72a4f37b7db"),
                "image": "",
                "tags": [],
                "pushTokens": [],
                "lastLogin": ISODate("2022-01-25T10:08:19.055Z"),
                "firstName": "dinesh",
                "lastName": "patel",
                "email": "dineshpatel@example.com",
                "infusionSoftId": "something",
                "role": "user",
                "__v": 0,
                "settings": {
                    "commentNotification": false,
                    "commentReplyNotification": true
                }
            },
            "threadText": "New Message",
            "reactions": [
                {
                    "authors": [ 
                        {
                            "_id": ObjectId("3687de8f8a5fd72a4f37b7bg"),
                            "image": "",
                            "tags": [],
                            "pushTokens": [],
                            "lastLogin": ISODate("2022-01-25T10:08:19.055Z"),
                            "firstName": "kayle",
                            "lastName": "hell",
                            "email": "kylehell@example.com",
                            "infusionSoftId": "8475151",
                            "role": "user",
                            "__v": 0,
                            "settings": {
                                "commentNotification": false,
                                "commentReplyNotification": true
                            }
                        }
                    ],
                    "_id": ObjectId("61ef856432753c196382c37d"),
                    "icon": "&#128528"
                }
            ],
            "createdAt": ISODate("2022-01-25T10:13:49.033Z"),
            "updatedAt": ISODate("2022-01-25T10:13:49.033Z"),
            "__v": 0
        }
    ]
}

如何为反应作者编写查找查询。 提前致谢!!

您可以尝试嵌套查找,

  • $lookup带频道线程集合,在let
  • 中传递频道id
  • $match 匹配 channelId 条件
  • $lookup 使用用户集合获取 authorId
  • 的作者信息
  • $lookup 使用用户集合获取 reactionsauthors 信息
  • $arrayElemAtauthorId
  • 获取第一个元素
  • $map 迭代 reactions 数组的循环,$filter 迭代 users 的循环并从 users 数组中获取匹配的作者用户信息,
  • $mergeObjects 合并 authors 和当前对象属性
  • $$REMOVE 删除 users 字段,因为现在不需要它
db.channel.aggregate([
  {
    $lookup: {
      from: "channelThread",
      let: { channelId: "$_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$$channelId", "$channelId"] } } },
        {
          $lookup: {
            from: "user",
            localField: "authorId",
            foreignField: "_id",
            as: "authorId"
          }
        },
        {
          $lookup: {
            from: "user",
            localField: "reactions.authors",
            foreignField: "_id",
            as: "users"
          }
        },
        {
          $addFields: {
            authorId: { $arrayElemAt: ["$authorId", 0] },
            reactions: {
              $map: {
                input: "$reactions",
                as: "r",
                in: {
                  $mergeObjects: [
                    "$$r",
                    {
                      authors: {
                        $filter: {
                          input: "$users",
                          cond: { $in: ["$$this._id", "$$r.authors"] }
                        }
                      }
                    }
                  ]
                }
              }
            },
            users: "$$REMOVE"
          }
        }
      ],
      as: "threads"
    }
  }
])

Playground