The integer problem mentioned in this article is actually not a problem of MongoDB, but a problem of PHP driver: MongoDB itself has two integer types, namely: 32-bit integer and 64-bit integer, but the old version of the PHP driver does not care whether the operating system is 32 The bit is still 64 bits, and all integers are treated as 32-bit integers, resulting in 64-bit integers being truncated. In order to solve this problem while maintaining compatibility as much as possible, the new version of the PHP driver has added the mongo.native-long option, in order to treat integers as 64-bit in 64-bit operating systems. If you are interested, please refer to: 64- bit
integers in MongoDB.
So does the PHP driver really solve the integer problem completely? NO! There are still bugs when dealing with group operations:
To illustrate the problem, let’s first generate some test data:
<?php
ini_set(‘mongo.native_long’, 1);
$instance = new Mongo();
$instance = $instance->selectCollection(‘test’, ‘test’);
for ($i = 0; $i < 10; $i++) {
$instance->insert(array(
‘group_id’ => rand(1, 5),
‘count’ => rand(1, 5),
));
}
?>
Let’s use the group operation to group by group_id and calculate the count:
<?php
ini_set(‘mongo.native_long’, 1);
$instance = new Mongo();
$instance = $instance->selectCollection(‘test’, ‘test’);
$keys = array(‘group_id’ => 1);
$initial = array(‘count’ => 0);
$reduce = ‘
function(obj, prev) {
Prev.count += obj.count;
}
‘;
$result = $instance->group($keys, $initial, $reduce);
var_dump($result);
?>
The result was different from what was expected, the count did not realize the accumulation, but became [object
Object], at present, if you must use the group operation, there are two ways to alleviate this problem:
method one:
ini_set(‘mongo.native_long’, 0);
Method Two:
$initial = array(‘count’ => (float)0);
These two methods are expedient measures to solve the symptoms but not the root cause. Since there is a problem with the implementation of group in the current PHP driver, we will bypass it and use other methods to achieve the same function. This method is MapReduce:
<?php
ini_set(‘mongo.native_long’, 1);
$instance = new Mongo();
$instance = $instance->selectDB(‘test’);
$map = ‘
function() {
emit(this.group_id, this.count);
}
‘;
$reduce = ‘
function(key, values) {
var sum = 0;
for (var index in values) {
sum += values[index];
}
return sum;
}
‘;
$result = $instance->command(array(
‘mapreduce’ => ‘test’,
‘out’ => ‘name’,
‘map’ => $map,
‘reduce’ => $reduce
));
$result = iterator_to_array($instance->{$result[‘result’]}->find());
var_dump($result);
?>
Explanation: Although it seems a little inefficient for MapReduce to generate a new Collection on the surface, we can pre-generate it regularly, which is equivalent to maintaining a cache table, as long as the real-time requirements are not too high.
It takes three steps to put an elephant in the refrigerator, but using MapReduce only requires two steps of Map and Reduce. Here is a PDF document that vividly illustrates the GROUP in MySQL.
The correspondence between BY and MapReduce in MongoDB:
In addition, there are many materials for reference, such as: MongoDB Aggregation III: Map-Reduce Basics.
Note: The software version is MongoDB 1.6.5, PECL Mongo 1.1.4. Different versions may have different conclusions.