MongoDB-使用嵌套对象和可变键进行聚合
我有一份文件描述了摄像机在15分钟内观察到的不同事物的数量。看起来是这样的: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"),
{
"_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"
}
}])
请在此处尝试: