我有一个文档,描述了在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
}
}
}
data.counts
对象内的键随每个文档更改,并引用以后获取的其他数据。 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}},
]);
这将进行分组并返回数组中的所有segments
。
我还希望在data.counts
内汇总信息,以便获得每日组中所有相同密钥的值之和。
这将使我免于在每个15分钟的段中使用相同的键对值求和的另一个服务循环。例如。查询将返回如下内容:
{
"_id" : "2019-02-27",
"counts" : {
"5b434d05da1f0e00252566be" : 351,
"5b434d05da1f0e00252566cc" : 194,
"5b434d05da1f0e00252566ca" : 111
... any other keys that were found within a day
}
}
如何修改已有的查询,或使用其他查询?
谢谢!
答案 0 :(得分:1)
您可以使用$facet
流水线阶段创建两个子流水线;一个用于segments
,另一个用于counts
。通过使用$zip
将它们缝合在一起,并使用$map
合并从zip生成的每个2元素数组,可以连接这些子管道。请注意,只有在子管道输出相同大小的排序数组时,此方法才能正常工作,这就是为什么我们在每个子管道中按start_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"
}
}])
在这里尝试:Mongoplayground。