我是MongoDB的新手。考虑以下集合:
{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"statistics" : {
"members" : {
"topPerformers" : {
"hours" : [
{
"workHour" : 10,
"Darth Vader" : 72,
"Walrus Man" : 80,
"Imperial Stromtrooper" : 60
},
{
"workHour" : 11,
"Darth Vader" : 142,
"Walrus Man" : 115,
"Imperial Stromtrooper" : 100
},
{
"workHour" : 12,
"Darth Vader" : 116,
"Walrus Man" : 81,
"Imperial Stromtrooper" : 113
},
{
"workHour" : 13,
"Darth Vader" : 128,
"Walrus Man" : 90,
"Imperial Stromtrooper" : 141
},
{
"workHour" : 14,
"Darth Vader" : 95,
"Walrus Man" : 118,
"Imperial Stromtrooper" : 116
},
{
"workHour" : 15,
"Darth Vader" : 91,
"Walrus Man" : 93,
"Imperial Stromtrooper" : 124
},
{
"workHour" : 16,
"Darth Vader" : 144,
"Walrus Man" : 95,
"Imperial Stromtrooper" : 111
},
{
"workHour" : 17,
"Darth Vader" : 143,
"Walrus Man" : 72,
"Imperial Stromtrooper" : 136
},
{
"workHour" : 18,
"Darth Vader" : 54,
"Walrus Man" : 88,
"Imperial Stromtrooper" : 87
},
{
"workHour" : 19,
"Darth Vader" : 82,
"Walrus Man" : 146,
"Imperial Stromtrooper" : 67
},
{
"workHour" : 20,
"Darth Vader" : 88,
"Walrus Man" : 136,
"Imperial Stromtrooper" : 52
},
{
"workHour" : 21,
"Darth Vader" : 92,
"Walrus Man" : 113,
"Imperial Stromtrooper" : 124
},
{
"workHour" : 22,
"Darth Vader" : 91,
"Walrus Man" : 68,
"Imperial Stromtrooper" : 128
},
{
"workHour" : 23,
"Darth Vader" : 125,
"Walrus Man" : 64,
"Imperial Stromtrooper" : 84
},
{
"workHour" : 0,
"Darth Vader" : 97,
"Walrus Man" : 108,
"Imperial Stromtrooper" : 75
}
]
}
}
}
}
每天1天的记录都是这样的,例如我每天在集合中有30个文件。我可以使用我想要的日期范围db.getCollection('name').find({ date: { $gte: new ISODate(), $lt: new ISODate() } })
,然后如果我选择整个月的记录,我可以循环statistics.members.topPerformers.hours
并计算当天每个成员的总数客户端使用Javascript,如:
statistics.members.topPerformers.hours.forEach((hour) => {
Object
.keys(hour)
.filter(key => key !== 'workHour')
.forEach((key) => {
result[key] = (result[key] || 0) + hour[key];
});
});
我可以使用Mongo在服务器端执行并返回修改后的结果,例如:
{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"statistics" : {
"members" : {
"topPerformers" : {
"hours" : [
{
"workHour" : 10,
"Darth Vader" : 2512,
"Walrus Man" : 1423,
"Imperial Stromtrooper" : 1487
},
]
}
}
}
答案 0 :(得分:0)
您可以运行一个聚合管道,该管道利用 $match
运算符管道阶段按给定的日期范围过滤集合中的文档,前面的 {{3} } 运算符展平嵌入的小时数组,然后您可以使用 $unwind
管道对非规范化文档进行分组并计算总和。
以下mongo shell操作演示了以上内容:
var start = new Date();
start.setHours(0,0,0,0);
var end = new Date();
end.setHours(23,59,59,999);
db.collection.aggregate([
{ "$match": { "date": { "$gte": start, "$lte": end } } },
{ "$unwind": "$statistics.members.topPerformers.hours" },
{
"$group": {
"_id": "$_id",
"date": { "$first": "$date" },
"workHour" : {
"$sum": "$statistics.members.topPerformers.hours.workHour"
},
"Darth Vader" : {
"$sum": "$statistics.members.topPerformers.hours.Darth Vader"
},
"Walrus Man" : {
"$sum": "$statistics.members.topPerformers.hours.Walrus Man"
},
"Imperial Stromtrooper" : {
"$sum": "$statistics.members.topPerformers.hours.Imperial Stromtrooper"
}
}
}
]);
示例输出
{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"workHour" : 231.0,
"Darth Vader" : 1560.0,
"Walrus Man" : 1467.0,
"Imperial Stromtrooper" : 1518.0
}
虽然没有必要,但您可以通过附加 $group
管道来重塑最终文档字段
db.collection.aggregate([
{ "$match": { "date": { "$gte": start, "$lte": end } } },
{ "$unwind": "$statistics.members.topPerformers.hours" },
{
"$group": {
"_id": "$_id",
"date": { "$first": "$date" },
"workHour" : {
"$sum": "$statistics.members.topPerformers.hours.workHour"
},
"Darth Vader" : {
"$sum": "$statistics.members.topPerformers.hours.Darth Vader"
},
"Walrus Man" : {
"$sum": "$statistics.members.topPerformers.hours.Walrus Man"
},
"Imperial Stromtrooper" : {
"$sum": "$statistics.members.topPerformers.hours.Imperial Stromtrooper"
}
}
},
{
"$project": {
"date": 1,
"statistics.members.topPerformers.hours.workHour": "$workHour",,
"statistics.members.topPerformers.hours.Darth Vader": "$Darth Vader",
"statistics.members.topPerformers.hours.Walrus Man": "$Walrus Man",
"statistics.members.topPerformers.hours.Imperial Stromtrooper": "$Imperial Stromtrooper"
}
}
])
<强>输出强>
{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"statistics" : {
"members" : {
"topPerformers" : {
"hours" : {
"workHour" : 231.0,
"Darth Vader" : 1560.0,
"Walrus Man" : 1467.0,
"Imperial Stromtrooper" : 1518.0
}
}
}
}
}