繁体   English   中英

使用 MongoDB 聚合管道将嵌套数组元素投影到顶层

[英]Project nested array element to top level using MongoDB aggregation pipeline

我有一个包含表单文档的groups集合

{
    "_id": "g123"
    ...,
    "invites": [
        {
            "senderAccountId": "a456",
            "recipientAccountId": "a789"
        },
        ...
    ]
}

我希望能够列出用户收到的所有邀请。

我想在groups集合上使用聚合管道,过滤所有组以仅返回用户被邀请加入的组。

db.groups.aggregate([
    {
        $match: {
            "invites.recipientAccountID": "<user-id>"
        }
    }
])

最后我想投影这个组数组以结束形式的数组

[
    {
         "senderAccountId": "a...",
         "recipientAccountId": "<user-id>",
         "groupId": "g...", // Equal to "_id" field of document.
    },
    ...
]

但是我在聚合管道中缺少将嵌套的senderAccountIdrecipientAccountId字段带到顶层的“项目”步骤。 我在 MongoDB 查询和聚合管道中看到了在线投影示例,但我找不到将文档数组字段的先前匹配元素投影到顶级的示例。

我想过使用数组更新运算符来引用匹配的元素,但使用这种方法无法取得任何有意义的进展。

我想你想要的是$replaceRoot

db.collection.aggregate([
  {$match: {"invites.recipientAccountId": "a789"}},
  {$set: {
      invites: {$first: {
          $filter: {
            input: "$invites",
            cond: {$eq: ["$$this.recipientAccountId", "a789"]}
          }
      }}
  }},
  {$replaceRoot: {newRoot: {$mergeObjects: ["$invites", {group: "$_id"}]}}}
])

playground 示例中查看它是如何工作的

有多种方法可以做到这一点,结合使用unwindproject也可以。 Unwind将为每个project创建一个 object,让您选择如何使用当前变量构建结果。

db.collection.aggregate([
  {
    "$unwind": "$invites"
  },
  {
    "$match": {
      "invites.recipientAccountId": "a789"
    }
  },
  {
    "$project": {
      recipientAccountId: "$invites.recipientAccountId",
      senderAccountId: "$invites.senderAccountId",
      groupId: "$_id",
      _id: 0 // don't show _id key:value
    }
  }
])

您还可以使用 nimrod serok 的$replaceRoot代替$project一个

  {$replaceRoot: {newRoot: {$mergeObjects: ["$invites", {group: "$_id"}]}}}

操场

nimrod serok 的解决方案可能会好一点,因为我的先展开它然后再匹配它,但我相信我的更具可读性

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM