我需要一个由php的mongo地图减少功能
这是我的mongo结构
[_id] => MongoId Object (
[$id] => 4fcf2f2313cfcd2454500000d
)
[id] => 454
[table] => people
[news] => Array (
[03-06-2012] => 2
[04-06-2012] => 3
[05-06-2012] => 5
[06-06-2012] => 4
)在这里,我尝试用下面的代码对数组消息求和,
$map = new MongoCode('function() { emit(this.news, 1); }');
$reduce = new MongoCode('function(previous, current) {
var count = 0;
for (index in current) {
count = count + current[index];
}
return count;
}');
$sales = $db->command(array(
'mapreduce' => 'mycollection',
'map' => $map,
'reduce' => $reduce,
'query' => array('table' => 'people'),
'out' => 'news'
));
//pr($sales);exit;
$users = $db->selectCollection($sales['result'])->find();
foreach ($users as $user) {
//echo "{$user['_id']} had {$user['value']} sale(s).\n";
pr($user);
}当pr($user)
Array
(
[_id] => Array
(
[04-06-2012] => 0
[08-06-2012] => 2
[11-06-2012] => 6
)
[value] => 39540
)我期望的值将是8而不是39540。
如何纠正此函数,如何将字段sum作为'news‘的数组sum添加到原始集合(Mycollection)?
我不熟悉mongo中的map reduce函数。
发布于 2012-06-13 07:45:51
在调用emit()时,第一个参数是要减少的键(本例中为grouping )。第二个参数是为该键发出的值,可以是任何值。对于您的示例,您可能想要发出news字段中所有值的总和,使用文档的ID作为您的键:
var map = function() {
var total = 0;
for (count in this.news) {
total += count;
}
emit(this._id, total);
}在这种情况下,可以使用占位符reduce函数(因为每个发出的键都是唯一的,所以需要做的缩减很少):
var reduce = function(key, values) {
var total = 0;
values.forEach(function(v) { total += v; });
return total;
}但是,正如我在Google Group post中提到的,使用纯PHP可能会更好:
$cursor = $collection->find(array(), array('news' => 1));
$cursor->snapshot();
foreach ($cursor as $document) {
$collection->update(
array('_id' => $document['_id']),
array('$set' => array('sum' => array_sum($document['news']))),
array('multiple' => false)
);
}使用map/reduce,您仍然必须检查其结果并更新您的记录。这将避免通过Mongo执行JavaScript的需要,并且应该会更有性能。如果您可以在news字段按文档进行修改时利用$inc更新sums,那就更好了。对于初始化整个集合中的sum字段,或者在与每个文档的增量不同步时纠正任何漂移,上面的代码片段仍然很有用。
注意:有关上述示例中该方法调用背后的原因,请参阅文档中的snapshot()。
发布于 2012-10-10 19:03:55
而jmikola的回答给了我处理mongo map reduce函数的wright track。
我添加这个答案是为了帮助未来的访问者。
下面的map-reduce函数完全符合我的要求。这会将新闻字段中的所有值相加到在command中通过添加("out" => "news")创建的名为news的新集合。
映射-Reduce函数
$map = new MongoCode('function() {
var total = 0;
for (count in this.news) {
total += this.news[count];
}
emit(this._id, {id: this.id, total: total});
}');
$reduce = new MongoCode('function(key, values) {
var result = {id: null, total: 0};
values.forEach(function(v) {
result.id = v.id;
result.total = v.total;
});
return result;
}');
$sales = $db->command(array(
'mapreduce' => 'mycollection', // collection name
'map' => $map,
'reduce' => $reduce,
'query' => array('table' => 'people'),
"out" => "news" // new collection name
));结果将是news集合,其中total为sum,实际文档为id
输出
[_id] => MongoId Object (
[$id] => 4fd8993a13cfcd4e42000000
)
[value] => Array (
[id] => 454
[total] => 14
)https://stackoverflow.com/questions/10978975
复制相似问题