我是MongoDb的新手并且有一份工作(我想)MapReduce或Aggregation。
我有一个“发票”集合,其中包含以下格式的文档:
{
date: 'some unix timestamp',
total: 12345,
paid: true
}
我需要显示一个表格,其中月份(jan-dec)为列,每年一行,以及单元格中月份总数(按付费和未付费)的总和。像这样:
| Jan | Feb | ...
2013 | 1,222 / 200 | 175 / 2,122 | ...
...
你能帮我搞好mongo命令吗? 也许我最好写一些JS代码在mongo中执行?
答案 0 :(得分:4)
我现在已经找到了使用MapReduce的解决方案。这是PHP中使用的:
$map = new MongoCode('
function() {
var d = new Date(this.date*1000);
emit({y: d.getFullYear(), m: d.getMonth()}, {
total: this.total,
notPaid: this.paid ? 0 : this.total,
count: 1
});
};
');
$reduce = new MongoCode('
function(month, values) {
result = { total: 0, notPaid: 0, count: 0 };
for (var i = 0; i < values.length; i++) {
result.total += values[i].total;
result.notPaid += values[i].notPaid;
result.count += values[i].count;
}
return result;
};
');
$result = $db->command(array(
'mapreduce' => 'invoices',
'map' => $map,
'reduce' => $reduce,
'out' => 'temp'
));
echo $result['timeMillis'];
现在结果在“临时”集合中,每月一份文件。它可以优化或增强吗?
答案 1 :(得分:3)
您可以使用聚合框架执行此操作:
db.invoices.aggregate( [
{
"$project" : {
"yr" : {
"$year" : "$date"
},
"mo" : {
"$month" : "$date"
},
"total" : 1,
"unpaid" : {
"$cond" : [
"$paid",
0,
"$total"
]
}
}
},
{
"$group" : {
"_id" : {
"y" : "$yr",
"m" : "$mo"
},
"total" : {
"$sum" : "$total"
},
"unpaid" : {
"$sum" : "$unpaid"
}
}
}
] )
您最后可以使用另一个$project
来提升输出,并使用$sort
对其进行排序,但这是它的基本功能核心。