【问题标题】:MongoDB $group pipeline (in Mongoose)MongoDB $group 管道(在 Mongoose 中)
【发布时间】:2014-01-06 15:38:01
【问题描述】:

我有一个 Mongo 集合,其中包含如下所示的文档:

{
    "record" : "1",
    "site_id" : "abc1",
    "month" : "2013-12",
    "recorded" : ISODate("2013-12-18T05:00:00.000Z"),
    "status" : "OK",
    "comment" : "blah blah blah..."
}

{
    "record" : "2",
    "site_id" : "abc1",
    "month" : "2013-12",
    "recorded" : ISODate("2013-12-18T06:00:00.000Z"),
    "status" : "OK",
    "comment" : "blah blah blah..."
}

{
    "record" : "3",
    "site_id" : "abc2",
    "month" : "2013-12",
    "recorded" : ISODate("2013-12-18T06:00:00.000Z"),
    "status" : "OK",
    "comment" : "blah blah blah..."
}

{
    "record" : "4",
    "site_id" : "abc2",
    "month" : "2013-12",
    "recorded" : ISODate("2013-12-18T11:00:00.000Z"),
    "status" : "ERROR",
    "comment" : "something wrong"
}

{
    "record" : "5",
    "site_id" : "abc2",
    "month" : "2013-11",
    "recorded" : ISODate("2013-11-17T08:00:00.000Z"),
    "status" : "OK",
    "comment" : "blah blah blah..."
}

我想使用 $group 运算符进行 Mongoose 调用,以返回每个 site_id 给定月份的最新记录(由 ISODate() 确定)的所有值。因此,对于 2013-12 月份,我想找回记录 2(abc1 是 2013-12 年最新的)和记录 4(abc2 是 2013-12 年最新的)。

我可以使用 map/reduce 函数来做到这一点,但我想知道仅使用 Mongoose API 和聚合框架(不调用 map/reduce 函数)是否可行。我觉得它应该是,但我无法让它工作!

【问题讨论】:

  • 您能否编辑问题以包含您所做的一些尝试以及哪些无效?使用聚合框架和管道,最好是按部就班地工作。

标签: mongodb mongoose aggregation-framework


【解决方案1】:

当使用aggregate 获取每个组的特定元素时,您需要在管道中包含$sort 阶段,在$group 之前将所需元素放在每个组的首位,以便您可以使用@ 987654324@ 运算符从该组中的第一个文档中挑选出您想要的字段。

在外壳中:

db.test.aggregate(
    {$match: {month: '2013-12'}}, 
    {$sort: {recorded: -1}}, 
    {$group: {
        _id: '$site_id', 
        record: {$first: '$record'},
        recorded: {$first: '$recorded'},
        status: {$first: '$status'},
        comment: {$first: '$comment'}
    }})

【讨论】:

    【解决方案2】:

    假设您的所有文档都存在所有相同的字段,您可以使用聚合框架查找每个月份和站点分组的“最后”记录。

    注意:虽然下面的查询返回了预期的结果,但它的效率或可扩展性并不高,因此您应该使用具有代表性的数据集进行测试。 $group 方法在第一步中需要对比您实际想要返回的数据多得多的数据进行排序。另一种方法是使用$sort$limit 为每个站点运行一个聚合。 MongoDB 2.4+ 具有 an optimization 用于聚合框架用例 $sort 后跟 $limit(因为要保留的前 n 个结果的数量是已知的),因此多个高效查询的总体执行时间可能比单个效率低下。

    样本聚合:

    db.sites.aggregate(
    
        // Need to sort first so "last" makes sense in the $group
        { $sort: {
            month : 1,
            site_id: 1,
            recorded: 1,
        }},
    
        // Find the last monthly record for each site_id
        { $group: {
            _id: { "month" : "$month", site_id: "$site_id" },
            record: { $last: "$record" },
            site_id: { $last: "$site_id" },
            month: { $last: "$month" },
            recorded: { $last: "$recorded" },
            status: { $last: "$status" },
            comment: { $last: "$comment" }
        }}
    
    )
    

    示例结果:

    {
        "result" : [
            {
                "_id" : {
                    "month" : "2013-12",
                    "site_id" : "abc2"
                },
                "record" : "4",
                "site_id" : "abc2",
                "month" : "2013-12",
                "recorded" : ISODate("2013-12-18T11:00:00Z"),
                "status" : "ERROR",
                "comment" : "something wrong"
            },
            {
                "_id" : {
                    "month" : "2013-12",
                    "site_id" : "abc1"
                },
                "record" : "2",
                "site_id" : "abc1",
                "month" : "2013-12",
                "recorded" : ISODate("2013-12-18T06:00:00Z"),
                "status" : "OK",
                "comment" : "blah blah blah..."
            }
        ],
        "ok" : 1
    }
    

    【讨论】:

      猜你喜欢
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 2015-05-12
      相关资源
      最近更新 更多