Need a map reduce function by mongo in php
This my mongo structure
[_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
)
Here I try to sum the array news with below code,
$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);
}
When pr($user)
Array
(
[_id] => Array
(
[04-06-2012] => 0
[08-06-2012] => 2
[11-06-2012] => 6
)
[value] => 39540
)
Where I expected a value will be 8 instead of 39540.
How I can correct this function and how to the add a field sum as array sum of ‘news’ to original collection(mycollection) ?
I am not familar with map reduce functions in mongo.
When calling
emit(), the first parameter is the key you’ll be reducing on (or grouping, for this example). The second parameter is the value being emitted for that key, which can be anything. For your example, you probably mean to emit the sum of all values in thenewsfield, using the document’s ID as your key:In this case, a placeholder reduce function can be used (since each emitted key will be unique, there’s very little reduction to be done):
However, as I mentioned in the Google Group post, you may be better off doing this with pure PHP:
With map/reduce, you’d still have to examine its results and update your records. This would avoid the need to execute JavaScript through Mongo, and should be more performant. And if you can utilize $inc to update the sums as the
newsfield is modified on a per-document basis, that will be even better. The above snippet would still be useful for initializingsumfields across the collection, or correcting any drift if things get out of sync with per-document increments.Note: see snapshot() in the documentation for the reasoning behind that method call in the example above.