仅对嵌入的文档数组进行分组

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

在 MongoDB 中,我想对嵌套在另一个文档中的文档数组进行分组,而不影响父文档。

数据库

db={
      "users": [
        {
          "firstName": "David",
          "lastName": "Mueller",
          "messages": [
            {
              "text": "hello",
              "type": "PERSONAL"
            },
            {
              "text": "test",
              "type": "DIRECT"
            }
          ]
        },
        {
          "firstName": "Mia",
          "lastName": "Davidson",
          "messages": [
            {
              "text": "hello world",
              "type": "DIRECT"
            },
            {
              "text": ":-)",
              "type": "PERSONAL"
            },
            {
              "text": "hi there",
              "type": "DIRECT"
            }
          ]
        }
      ]
    }

想要的结果

[
      {
        "firstName": "David",
        "lastName": "Mueller",
        "messages": [
          {
            "_id": "PERSONAL",
            "count": 1
          },
          {
            "_id": "DIRECT",
            "count": 1
          }
        ]
      },
      {
        "firstName": "Mia",
        "lastName": "Davidson",
        "messages": [
          {
            "_id": "PERSONAL",
            "count": 1
          },
          {
            "_id": "DIRECT",
            "count": 2
          }
        ]
      }
]

如果我有一个 ids 数组,我已经知道如何使用 $lookup 的内部管道来做到这一点,但我的问题是如何使用一组嵌入文档来做到这一点。


这是使用查找对具有 ids 的数组进行工作分组的示例。这不是解决方案,因为问题是关于嵌入式文档数组而不是 id 数组。提供此示例只是为了表明当 ids 而不是嵌入文档存储在数组中时,我可以归档所需的结果。

用于查找分组的数据库:

db={
  "users": [
    {
      "firstName": "David",
      "lastName": "Mueller",
      "messages": [
        1,
        2
      ]
    },
    {
      "firstName": "Mia",
      "lastName": "Davidson",
      "messages": [
        3,
        4,
        5
      ]
    }
  ],
  "messages": [
    {
      "_id": 1,
      "text": "hello",
      "type": "PERSONAL"
    },
    {
      "_id": 2,
      "text": "test",
      "type": "DIRECT"
    },
    {
      "_id": 3,
      "text": "hello world",
      "type": "DIRECT"
    },
    {
      "_id": 4,
      "text": ":-)",
      "type": "PERSONAL"
    },
    {
      "_id": 5,
      "text": "hi there",
      "type": "DIRECT"
    }
  ]
}

通过查找进行分组聚合:

db.users.aggregate([
  {
    "$lookup": {
      "from": "messages",
      "localField": "messages",
      "foreignField": "_id",
      "as": "messages",
      "pipeline": [
        {
          "$group": {
            "_id": "$type",
            "count": {
              "$sum": 1
            }
          }
        }
      ]
    }
  }
])

查找分组的结果(这是期望的结果):

[
  {
    "_id": ObjectId("5a934e000102030405000005"),
    "firstName": "David",
    "lastName": "Mueller",
    "messages": [
      {
        "_id": "PERSONAL",
        "count": 1
      },
      {
        "_id": "DIRECT",
        "count": 1
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000006"),
    "firstName": "Mia",
    "lastName": "Davidson",
    "messages": [
      {
        "_id": "PERSONAL",
        "count": 1
      },
      {
        "_id": "DIRECT",
        "count": 2
      }
    ]
  }
]

MongoDB Playground 中的这个示例


现在回到问题:我想归档相同的结果,但使用顶部提供的嵌入式文档数组。

我不知道如何做到这一点(我尝试了人工智能,很多谷歌搜索和其他论坛都没有成功,你是我放弃之前的最后一个资源),我知道我可以使用 $addField 和 $fitler 过滤嵌入数组,但不能我如何才能仅对嵌入数组进行分组。

请注意,这只是一个简单的例子,我的真实数据结构看起来不同,也可能使用其他分组函数,如 min、sum 等。但我只是想知道在使用查找时归档相同内容的一般方法。

我感谢任何帮助,谢谢你 🙂

mongodb mongodb-query aggregation-framework
1个回答
0
投票
  1. 放松
    messages
  2. _id
    (大概是用户 ID)和消息
    type
    进行分组;并使用
    $count
    设置 countType。
  3. 然后仅按
    _id
    重新分组并使用第一个
    doc
    (因为对于非消息字段是相同的)
    • 将每个
      {type: ..., count: countType}
      推入消息数组中。
    • 请注意,文档恢复为每个用户一份/
      _id
  4. doc.messages
    设置为上一步推送的数组
    messages
  5. 用新的
    doc
    替换根,它具有所有正确的信息
  6. (如果需要,也可以按
    _id
    排序。)
db.users.aggregate([
  { $unwind: "$messages" },
  {
    $group: {
      _id: {
        _id: "$_id",
        type: "$messages.type"
      },
      countType: { $count: {} },
      doc: { $first: "$$ROOT" }
    }
  },
  {
    $group: {
      _id: "$_id._id",
      doc: { $first: "$doc" },
      messages: {
        $push: {
          type: "$_id.type",
          count: "$countType"
        }
      }
    }
  },
  { $set: { "doc.messages": "$messages" } },
  { $replaceWith: "$doc" }
])

蒙戈游乐场

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