【问题标题】:Group documents by subdocument field按子文档字段对文档进行分组
【发布时间】:2017-12-31 22:49:49
【问题描述】:

我正在尝试使用 mongo 的聚合框架根据时间戳对集合进行分组,并使用 $out 将其输出到新集合。抱歉,我是 Mongo 的新手

我的收藏中有以下 JSON 结构

{
    "_id" : "1",
    "parent" : [
        {
            "child" : {
                "child_id" : "1",
                "timestamp" : ISODate("2010-01-08T17:49:39.814Z")
            }
        }
    ]
}

这是我一直在尝试的

db.mycollection.aggregate([
        { $project: { child_id: '$parent.child.child_id', timestamp: '$parent.child.timestamp' }},
        { $group: { cid: '$child_id', ts: { $max: '$timestmap'} }},
        { $out : 'mycollectiongrouped'}
        ]))

但是得到这个错误。任何想法,我想我可能不正确地使用该项目。

[thread1] 错误:命令失败:{ “好”:0, "errmsg" : "组聚合字段 'cid' 必须定义为对象内的表达式", “代码”:15951 } :聚合失败: _getErrorWithCode@src/mongo/shell/utils.js:25:13

【问题讨论】:

  • 您缺少_id 字段。您还应该考虑使用有效的日期对象。
  • 谢谢。关于我使用 ISODate() 的验证日期对象。将适当地编辑问题
  • “父”字段总是一个元素数组吗?你的mongod 是什么版本?
  • 是的,有多个孩子。我希望根据最大时间戳对孩子进行分组,因此我为每个父母获得一个具有最大时间戳的孩子。版本是 3.2.7

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:
db.collection.aggregate([
    {$group: { 
        _id: "$parent.child.child_id",
        timestamp: {$max: "$parent.child.timestamp"}
    }},
    {$project: {
        cid: {$arrayElemAt: ["$_id", 0]},
        ts: {$arrayElemAt: ["$timestamp", 0]},
        _id: 0
    }},
    {$out: "groupedCollection" }
])

您缺少_id,这是$group 管道阶段所必需的。话虽这么说,因为文档中的“父”字段是一个元素数组,$group 阶段应该是管道中的第一阶段。

通过将$group 阶段设置为第一阶段,您只需为每个组投影一个文档,而不是集合中的所有文档。

请注意,生成的文档字段是数组,因此在 $project 阶段使用 $arrayElemAt 运算符。

【讨论】:

  • 感谢您的回复和解释。现在我明白了,这是有道理的。在我的 Mongo Collection 上试了一下,效果很好。
【解决方案2】:

$group 需要一个 _id 字段。这个_id 决定了哪些文档被组合在一起。例如,如果您想按child_id 分组,则使用_id: "$child_id"。在这种情况下,您可以省略cid 字段(在这种情况下,您只需将cid 更改为_id)。

【讨论】:

    猜你喜欢
    • 2023-01-12
    • 2013-01-11
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    相关资源
    最近更新 更多