この記事で言及されている整数の問題は、実際には MongoDB の問題ではなく、PHP ドライバーの問題です。MongoDB 自体には 2 つの整数型、つまり 32 ビット整数と 64 ビット整数がありますが、古いバージョンのPHP ドライバーはオペレーティング システムを考慮しません。32 ビットでも 64 ビットでも、すべての整数は 32 ビット整数として扱われるため、64 ビット整数は切り捨てられます。可能な限り互換性を維持しながらこの問題を解決するために、新しいバージョンの PHP ドライバーには、64 ビット オペレーティング システムで整数を 64 ビットとして扱うための mongo.native-long オプションが追加されました。興味のある方は、MongoDB の 64 ビット整数を参照してください。
それでは、PHP ドライバーは整数の問題を本当に完全に解決できるのでしょうか? いいえ、グループ操作を扱う際にはまだバグがあります。
問題を説明するために、まずテスト データを生成しましょう:ini_set('mongo.native_long', 1);
$instance = new Mongo();
$instance = $instance->selectCollection('test', 'test');
for ($i = 0; $i $instance->insert(array(
'group_id' => rand(1, 5),
'count' => rand(1, 5),
));
}
?>
グループ操作を使用して、group_id に従ってグループ化し、合計の数を計算してみましょう:
ini_set('mongo.native_long', 1);
$instance = new Mongo();
$instance = $instance->selectCollection('test', 'test');
$keys = array('group_id' => 1);
$initial = array('count' => 0);
$reduce = '
関数(obj, prev) {
prev.count += obj.count;
}
';
$result = $instance->group($keys, $initial, $reduce);
var_dump($result);
?>
結果が期待したものと異なります。Count は累積を実現しませんが、[オブジェクト オブジェクト] になります。現時点では、グループ操作を使用する必要がある場合、この問題を軽減する 2 つの方法があります。
ini_set('mongo.native_long', 0);
$initial = array('count' => (float)0);
これらの 2 つの方法は、根本的な原因ではなく、症状を治療するための便宜的な手段です。現在の PHP ドライバーのグループの実装に問題があるため、それをバイパスし、他の方法を使用して同じ機能を実現します。 MapReduce は:
ini_set('mongo.native_long', 1);
$instance = new Mongo();
$instance = $instance->selectDB('test');
$map = '
関数() {
emit(this.group_id, this.count);
}
';
$reduce = '
関数(キー、値) {
var sum = 0;
for (値の変数インデックス) {
合計 += 値[インデックス];
}
返金額;
}
';
$result = $instance->command(array(
)'mapreduce' => 'test',
'map' => $map,
'reduce' => $reduce
));
$result = iterator_to_array($instance->gt;{$result['result']}->find());
var_dump($result);
?>
象を冷蔵庫に入れるには 3 つのステップが必要ですが、MapReduce を使用するには、Map と Reduce の 2 つのステップだけが必要です。これは、MySQL の GROUP BY と MongoDB の MapReduce の対応関係を明確に示した PDF ドキュメントです。