[英]MongoDB Map Reduce newbie (PHP)
我是地图减少概念的新手,即使我进展缓慢,我也发现了一些需要帮助的问题。
我有一个简单的集合,包括id,city和destination,如下所示:
{ "_id" : "5230e7e00000000000000000", "city" : "Boston", "to" : "Chicago" },
{ "_id" : "523fe7e00000000000000000", "city" : "New York", "to" : "Miami" },
{ "_id" : "5240e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
{ "_id" : "536fe4e00000000000000000", "city" : "Washington D.C.", "to" : "Boston" },
{ "_id" : "53ffe7e00000000000000000", "city" : "New York", "to" : "Boston" },
{ "_id" : "5740e1e00000000000000000", "city" : "Boston", "to" : "Miami" },
...
(请注意,此数据仅用于示例目的)
我想按城市分组包括计数在内的目的地:
{ "city" : "Boston", values : [{"Chicago",1}, {"Miami",2}] }
{ "city" : "New York", values : [{"Miami",1}, {"Boston",1}] }
{ "city" : "Washington D.C.", values : [{"Boston", 1}] }
为此,我开始玩这个函数来映射:
function() {
emit(this.city, this.to);
}
执行预期的分组。 我的reduce函数是这样的:
function(key, values) {
var reduced = {"to":[]};
for (var i in values) {
var item = values[i];
reduced.to.push(item);
}
return reduced;
}
这给出了一些预期的输出:
{ "_id" : ObjectId("522f8a9181f01e671a853adb"), "value" : { "to" : [ "Boston", "Miami" ] } }
{ "_id" : ObjectId("522f933a81f01e671a853ade"), "value" : { "to" : [ "Chicago", "Miami", "Miami" ] } }
{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : "Boston" }
正如你所看到的,我仍然没有计算重复的城市,但从上面可以看出,由于某种原因,输出中的最后结果看起来并不好。 我原以为是的
{ "_id" : ObjectId("5231f0ed81f01e671a853ae0"), "value" : { "to" : ["Boston"] } }
这与有一个项目的事实有什么关系吗? 有没有办法获得这个?
谢谢。
我看到你问的是PHP问题,但是你正在使用javascript来询问,所以我假设一个javascript答案会帮助你解决问题。 因此,这里是shell运行聚合所需的javascript。 我强烈建议让你的聚合在shell(或其他一些javascript编辑器)中工作,然后将其翻译成你选择的语言。 使用此方法可以更快地查看正在发生的事情。 然后你可以运行:
use admin
db.runCommand( { setParameter: 1, logLevel: 2 } )
检查所选语言的bson输出与shell的外观。 如果mongo位于前台,这将显示在终端中,否则您将查看日志。
将汇总框架[AF]中的路线与Mongo相加是相当紧张的。 AF更快更容易使用,然后map reduce [MR]。 虽然在这种情况下它们都有类似的问题,但只是推送到一个数组不会产生计数本身(在MR中,你需要在reduce函数中使用更多逻辑或使用finalize函数)。
使用AF提供的示例数据,此管道非常有用:
db.agg1.aggregate([
{$group:{
_id: { city: "$city", to: "$to" },
count: { $sum: 1 }
}},
{$group: {
_id: "$_id.city",
to:{ $push: {to: "$_id.to", count: "$count"}}
}}
]);
聚合框架只能在已知的字段上运行,但是许多管道操作都需要分解,因此需要将其作为一个考虑因素。 在上面,第一阶段计算需要的数量,其中有3个固定字段:源,目的地和计数。 第二阶段有2个固定字段,其中一个是一个数组,只是被推送到(最终形式的所有数据都在那里)。
对于MR,您可以这样做:
var map = function() {
var key = {source:this.city, dest:this.to};
emit(key, 1);
};
var reduce = function(key, values) {
return Array.sum(values);
};
然而,一个单独的功能必须漂亮。
如果您有任何其他问题,请不要犹豫。
最好,查理
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.