【问题标题】:Aggregate on array of embedded documents聚合嵌入文档数组
【发布时间】:2019-05-20 10:21:50
【问题描述】:

我有一个包含多个文档的 mongodb 集合。每个文档都有一个包含多个子文档的数组(或者我猜是嵌入式文档?)。这些子文档中的每一个都采用以下格式:

{
    "name": string,
    "count": integer
}

现在我要聚合这些子文档来查找

  1. 前 X 数及其名称。
  2. 与 1 相同,但名称必须与正则表达式匹配,然后才能进行排序和限制。

我已经为 1. 尝试了以下方法 - 它确实返回了前 X 但未排序,所以我不得不再次订购它们,这似乎效率低下。

[{
    $match: {
        _id: id
}
}, {
    $unwind: {
        path: "$array"
    }
}, {
    $sort: {
        'count': -1
    }
}, {
    $limit: x
}]

因为我对 mongodb 比较陌生,所以这对我来说很困惑。很高兴有任何帮助。提前致谢。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    排序必须包含数组名称,以避免稍后进行额外的排序。

    给定以下文档:

        {
          students: [{
            count: 4,
            name: "Ann"
          }, {
            count: 7,
            name: "Brad"
          }, {
            count: 6,
            name: "Beth"
          }, {
            count: 8,
            name: "Catherine"
          }]
        }
    

    例如,以下聚合查询将匹配任何包含字母“h”和“e”的名称。这需要在“$unwind”步骤之后进行,以便只保留您需要的那些。

        db.tests.aggregate([
          {$match: {
            _id: ObjectId("5c1b191b251d9663f4e3ce65")
          }},
          {$unwind: {
            path: "$students"
          }},
          {$match: {
            "students.name": /[he]/
          }},
          {$sort: {
            "students.count": -1
          }},
          {$limit: 2}
        ])
    

    这是给定上述输入的输出:

        { "_id" : ObjectId("5c1b191b251d9663f4e3ce65"), "students" : { "count" : 8, "name" : "Catherine" } }
        { "_id" : ObjectId("5c1b191b251d9663f4e3ce65"), "students" : { "count" : 6, "name" : "Beth" } }
    

    两个名字都包含字母“h”和“e”,输出从高到低排序。

    将limit设置为1时,输出限制为:

        { "_id" : ObjectId("5c1b191b251d9663f4e3ce65"), "students" : { "count" : 8, "name" : "Catherine" } }
    

    在这种情况下,只有在匹配名称后才会保留最高计数。

    ====================== 编辑额外的问题:

    是的,第一个 $match 可以更改为过滤特定大学。

          {$match: {
            university: "University X"
          }},
    

    这将提供一个或多个匹配的文档(如果您每年大约有一个文档),其余的聚合步骤仍然有效。

    如果需要,以下匹配将检索给定大学在给定学年的学生。

          {$match: {
            university: "University X",
            academic_year: "2018-2019"
          }},
    

    这应该缩小范围以获得正确的文档。

    【讨论】:

    • 谢谢!作为一个额外的问题:我可以更改第一个 $match 以匹配每个文档中存在一次的键而不是 _id?假设每个文档都有一个密钥 university,而我只想找到一所特定大学的学生。
    • 当然。刚刚编辑了答案以包含奖励问题。
    猜你喜欢
    • 1970-01-01
    • 2013-09-18
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2017-07-31
    • 1970-01-01
    • 2018-03-28
    • 2019-05-10
    相关资源
    最近更新 更多