Mongodb 聚合总和嵌入密钥对对象
Mongodb aggregate sum embedded key pair objects
我有以下合集
{
"pos": 1
"daily": 1,
"hourly": {
"15": 1,
"23": 4
}
}
每小时的范围从 0 到 23,我只想按位置分组,并希望聚合 ($sum) 每日和个人小时数。每小时有点欺骗我。
您可能应该为此使用 mapReduce,聚合框架无法遍历对象的键:
db.collection.mapReduce(
function() {
var obj = { "daily": this.daily, "hourly": {} };
for ( var x=0; x <= 23; x++ ) {
obj.hourly[x] = 0;
}
var hourly = this.hourly;
Object.keys(hourly).forEach(function(hour) {
obj.hourly[hour] += hourly[hour];
});
emit(null, obj);
},
function(key,values) {
var obj = { "daily": 0, "hourly": {} };
for ( var x=0; x <= 23; x++ ) {
obj.hourly[x] = 0;
}
values.forEach(function(value) {
obj.daily += value.daily;
Object.keys(value.hourly).forEach(function(hour) {
obj.hourly[hour] += value.hourly[hour];
});
});
return obj;
},
{ "out": { "inline": 1 } }
)
或者如果你的意思是你只想要 "hourly" 的总数,那么这样做:
db.collection.mapReduce(
function() {
var obj = { "daily": this.daily, "hourly": 0 };
var hourly = this.hourly;
hourly.forEach(function(hour) {
obj.hourly+= hourly[hour];
});
emit(null, obj);
},
function(key,values) {
var obj = { "daily": 0, "hourly": 0 };
values.forEach(function(value) {
obj.daily += value.daily;
obj.hourly += value.hourly;
});
return obj;
},
{ "out": { "inline": 1 } }
)
使用聚合框架执行此操作看起来非常糟糕。在这里缩短时间,但你应该看到基本要求是什么:
db.collection.aggregate([
{ "$group": {
"_id": null,
"daily": { "$sum": "$daily" },
"0": { "$sum": "$hourly.0" },
"1": { "$sum": "$hourly.1" },
"2": { "$sum": "$hourly.2" },
"3": { "$sum": "$hourly.3" },
"4": { "$sum": "$hourly.4" },
"5": { "$sum": "$hourly.5" },
"6": { "$sum": "$hourly.6" }
}},
{ "$project": {
"daily": 1,
"hourly": {
"0": "[=12=]",
"1": "",
"2": "",
"3": "",
"4": "",
"5": "",
"6": ""
}
}}
])
或者再次计算 "hourly" 个值的总和,
db.collection.aggregate([
{ "$group": {
"_id": null,
"daily": { "$sum": "$daily" },
"hourly": {
"$sum": { "$add": [
"$hourly.0",,
"$hourly.1",
"$hourly.2",
"$hourly.3",
"$hourly.4",
"$hourly.5",
"$hourly.6"
]}
}
}}
])
您当然可以使用代码生成聚合管道阶段,因为它们只是数据结构。因此,可以使用 mapReduce 示例(循环 0..23)中所示的类似方法来生成。
我有以下合集
{
"pos": 1
"daily": 1,
"hourly": {
"15": 1,
"23": 4
}
}
每小时的范围从 0 到 23,我只想按位置分组,并希望聚合 ($sum) 每日和个人小时数。每小时有点欺骗我。
您可能应该为此使用 mapReduce,聚合框架无法遍历对象的键:
db.collection.mapReduce(
function() {
var obj = { "daily": this.daily, "hourly": {} };
for ( var x=0; x <= 23; x++ ) {
obj.hourly[x] = 0;
}
var hourly = this.hourly;
Object.keys(hourly).forEach(function(hour) {
obj.hourly[hour] += hourly[hour];
});
emit(null, obj);
},
function(key,values) {
var obj = { "daily": 0, "hourly": {} };
for ( var x=0; x <= 23; x++ ) {
obj.hourly[x] = 0;
}
values.forEach(function(value) {
obj.daily += value.daily;
Object.keys(value.hourly).forEach(function(hour) {
obj.hourly[hour] += value.hourly[hour];
});
});
return obj;
},
{ "out": { "inline": 1 } }
)
或者如果你的意思是你只想要 "hourly" 的总数,那么这样做:
db.collection.mapReduce(
function() {
var obj = { "daily": this.daily, "hourly": 0 };
var hourly = this.hourly;
hourly.forEach(function(hour) {
obj.hourly+= hourly[hour];
});
emit(null, obj);
},
function(key,values) {
var obj = { "daily": 0, "hourly": 0 };
values.forEach(function(value) {
obj.daily += value.daily;
obj.hourly += value.hourly;
});
return obj;
},
{ "out": { "inline": 1 } }
)
使用聚合框架执行此操作看起来非常糟糕。在这里缩短时间,但你应该看到基本要求是什么:
db.collection.aggregate([
{ "$group": {
"_id": null,
"daily": { "$sum": "$daily" },
"0": { "$sum": "$hourly.0" },
"1": { "$sum": "$hourly.1" },
"2": { "$sum": "$hourly.2" },
"3": { "$sum": "$hourly.3" },
"4": { "$sum": "$hourly.4" },
"5": { "$sum": "$hourly.5" },
"6": { "$sum": "$hourly.6" }
}},
{ "$project": {
"daily": 1,
"hourly": {
"0": "[=12=]",
"1": "",
"2": "",
"3": "",
"4": "",
"5": "",
"6": ""
}
}}
])
或者再次计算 "hourly" 个值的总和,
db.collection.aggregate([
{ "$group": {
"_id": null,
"daily": { "$sum": "$daily" },
"hourly": {
"$sum": { "$add": [
"$hourly.0",,
"$hourly.1",
"$hourly.2",
"$hourly.3",
"$hourly.4",
"$hourly.5",
"$hourly.6"
]}
}
}}
])
您当然可以使用代码生成聚合管道阶段,因为它们只是数据结构。因此,可以使用 mapReduce 示例(循环 0..23)中所示的类似方法来生成。