【问题标题】:How to do the nested count in MongoDB?如何在 MongoDB 中进行嵌套计数?
【发布时间】:2020-12-21 13:07:07
【问题描述】:

我的电子邮件消息应用程序使用如下所示的 DB 架构:

db={
  "archives": [
    {
      "header": {
        "subject": "message-1",
        "message-id": "a"
      }
    },
    {
      "header": {
        "subject": "Re:message-1",
        "message-id": "b",
        "reply-to": [
          "a"
        ]
      }
    },
    {
      "header": {
        "subject": "Re:message-1",
        "message-id": "c",
        "reply-to": [
          "a"
        ]
      }
    },
    {
      "header": {
        "subject": "message-2",
        "message-id": "d"
      }
    },
    {
      "header": {
        "subject": "Re:message-2",
        "message-id": "e",
        "reply-to": [
          "d"
        ],
        
      }
    }
  ]
}

我可以像这样列出所有开始的电子邮件(那些没有reply-to 标签的):

db.archives.aggregate([
  {
    $match: {
      "header.reply-to": {
        $exists: false
      }
    }
  }
])

这表明只有 message-id: amessage-id: d 是起始电子邮件:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "header": {
      "message-id": "a",
      "subject": "message-1"
    }
  },
  {
    "_id": ObjectId("5a934e000102030405000003"),
    "header": {
      "message-id": "d",
      "subject": "message-2"
    }
  }
]

我不知道如何计算每封起始电子邮件的回复数。在这个例子中:

  • 消息 ID:A2 个回复
  • 消息 ID:D1 个回复

我在 MongoDB 游乐场发布了这个示例:https://mongoplayground.net/p/H6IT0SfCqBp

【问题讨论】:

    标签: mongodb count aggregate


    【解决方案1】:
    • $lookup 与同一个集合,将header.message-id 作为localField 传递,将header.reply-to 作为foreignField 传递
    • $size 获取 repliesCount 数组中的总元素
    db.archives.aggregate([
      { $match: { "header.reply-to": { $exists: false } } },
      {
        $lookup: {
          from: "archives",
          localField: "header.message-id",
          foreignField: "header.reply-to",
          as: "repliesCount"
        }
      },
      { $addFields: { repliesCount: { $size: "$repliesCount" } } }
    ])
    

    Playground

    【讨论】:

    • 我不知道怎么做,但是我已经进行了多次比较,您的代码的执行速度比 Minsky 的执行速度快了大约 20 倍,后者已经非常快了。太棒了,非常感谢。
    • 如果您指定了索引,此方法将使用索引。记住这件事,如果您在第二阶段或之后匹配您的条件,那么这将不会使用索引。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 2020-02-09
    • 2020-04-13
    • 1970-01-01
    • 2022-06-23
    相关资源
    最近更新 更多