MongoDB-使用嵌套对象和可变键进行聚合

MongoDB-使用嵌套对象和可变键进行聚合,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有一份文件描述了摄像机在15分钟内观察到的不同事物的数量。看起来是这样的: { "_id" : ObjectId("5b1a709a83552d002516ac19"), "start" : ISODate("2018-06-08T11:45:00.000Z"), "end" : ISODate("2018-06-08T12:00:00.000Z"), "recording" : ObjectId("5b1a654683552d002516ac16"),

我有一份文件描述了摄像机在15分钟内观察到的不同事物的数量。看起来是这样的:

{
    "_id" : ObjectId("5b1a709a83552d002516ac19"),
    "start" : ISODate("2018-06-08T11:45:00.000Z"),
    "end" : ISODate("2018-06-08T12:00:00.000Z"),
    "recording" : ObjectId("5b1a654683552d002516ac16"),
    "data" : {
        "counts" : {
            "5b434d05da1f0e00252566be" : 12,
            "5b434d05da1f0e00252566cc" : 4,
            "5b434d05da1f0e00252566ca" : 1
        }
    }
}
{
    "_id" : "2019-02-27",
    "counts" : {
        "5b434d05da1f0e00252566be" : 351,
        "5b434d05da1f0e00252566cc" : 194,
        "5b434d05da1f0e00252566ca" : 111
        ... any other keys that were found within a day
    }
}
数据中的键。对每个文档进行计数
对象更改,并引用以后获取的其他数据。data.counts中有无限数量的键(但通常约为20个)

我试图将所有这些15分钟的文档聚合到每日聚合的文档

我现在的问题是:

db.getCollection("segments").aggregate([
    {$match:{
       "recording": ObjectId("5bf7f68ad8293a00261dd83f")
    }}, 
    {$project:{
        "start": 1,
        "recording": 1,
        "data": 1
    }},
    {$group:{
        _id: { $dateToString: { format: "%Y-%m-%d", date: "$start" } },
        "segments": { $push: "$$ROOT" }
    }},
    {$sort: {_id: -1}},
]);
这将进行分组并返回数组中的所有

我还希望聚合
data.counts
中的信息,以便获得daily组中所有相同键的值之和

这将使我避免在每个15分钟的段中使用相同的键进行另一个服务循环求和值。例如,查询将返回如下内容:

{
    "_id" : ObjectId("5b1a709a83552d002516ac19"),
    "start" : ISODate("2018-06-08T11:45:00.000Z"),
    "end" : ISODate("2018-06-08T12:00:00.000Z"),
    "recording" : ObjectId("5b1a654683552d002516ac16"),
    "data" : {
        "counts" : {
            "5b434d05da1f0e00252566be" : 12,
            "5b434d05da1f0e00252566cc" : 4,
            "5b434d05da1f0e00252566ca" : 1
        }
    }
}
{
    "_id" : "2019-02-27",
    "counts" : {
        "5b434d05da1f0e00252566be" : 351,
        "5b434d05da1f0e00252566cc" : 194,
        "5b434d05da1f0e00252566ca" : 111
        ... any other keys that were found within a day
    }
}
如何修改已有的查询,或使用其他查询

谢谢

您可以使用pipeline阶段创建两个子管道;一个用于
,另一个用于
计数
。这些子管道可以通过使用将它们缝合在一起并合并zip生成的每个2元素数组来连接。注意,只有当子管道输出相同大小的排序数组时,这才会正常工作,这就是为什么我们在每个子管道中按
start\u date
进行分组和排序

问题是:

db.getCollection("segments").aggregate([{
    $match: {
        recording: ObjectId("5b1a654683552d002516ac16")
    }
}, {
    $project: {
        start: 1,
        recording: 1,
        data: 1,
        start_date: { $dateToString: { format: "%Y-%m-%d", date: "$start" }}
    }
}, {
    $facet: {
        segments_pipeline: [{
            $group: {
                _id: "$start_date",
                segments: {
                    $push: {
                        start: "$start",
                        recording: "$recording",
                        data: "$data"
                    }
                }
            }
        }, {
            $sort: {
                _id: -1
            }
        }],
        counts_pipeline: [{
            $project: {
                start_date: "$start_date",
                count: { $objectToArray: "$data.counts" }
            }
        }, {
            $unwind: "$count"
        }, {
            $group: {
                _id: {
                    start_date: "$start_date",
                    count_id: "$count.k"
                },
                count_sum: { $sum: "$count.v" }
            }
        }, {
            $group: {
                _id: "$_id.start_date",
                counts: {
                    $push: {
                        $arrayToObject: [[{
                            k: "$_id.count_id",
                            v: "$count_sum"
                        }]]
                    }
                }
            }
        }, {
            $project: {
                counts: { $mergeObjects: "$counts" }
            }
        }, {
            $sort: {
                _id: -1
            }
        }]
    }
}, {
    $project: {
        result: {
            $map: {
                input: { $zip: { inputs: ["$segments_pipeline", "$counts_pipeline"] }},
                in: { $mergeObjects: "$$this" }
            }
        }
    }
}, {
    $unwind: "$result"
}, {
    $replaceRoot: {
        newRoot: "$result"
    }
}])
请在此处尝试: