PHP操作MongoDB时的整数问题及对策说明


Posted in PHP onMay 02, 2011

MongoDB本身有两种整数类型,分别是:32位整数和64位整数,但旧版的PHP驱动不管操作系统是32位还是64位,把所有整数都当做32位整数处理,结果导致64位整数被截断。为了在尽可能保持兼容性的前提下解决这个问题,新版PHP驱动加入了mongo.native-long选项,以期在64位操作系统中把整数都当做64位来处理,有兴趣的可参考:64-bit integers in MongoDB

那么PHP驱动真的完全解决了整数问题么?NO!在处理group操作的时候还有BUG

为了说明问题,我们先来生成一些测试数据:

<?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), 
)); 
} 
?>

下面让我们使用group操作,根据group_id分组,汇总计算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); 
?>

结果和预想的有出入,count没有实现累加,而是变成了[object Object],目前,如果必须使用group操作,那么有两种方法可以缓解这个问题:
ini_set('mongo.native_long', 0); 
$initial = array('count' => (float)0);

这两种方法都是治标不治本的权宜之计,既然当前PHP驱动里group的实现有问题,那我们就绕开它,用其它的方式实现同样的功能,这个方式就是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', 
'map' => $map, 
'reduce' => $reduce 
)); 
$result = iterator_to_array($instance->{$result['result']}->find()); 
var_dump($result); 
?>

把大象放冰箱里需要三步,而使用MapReduce仅仅需要Map和Reduce两步即可,这里有一个PDF文档生动的说明了MySQL中GROUP BY和MongoDB中MapReduce的对应关系:

PHP操作MongoDB时的整数问题及对策说明 

SQL to MongoDB

此外,还有很多资料可供参考,如:MongoDB Aggregation III: Map-Reduce Basics

说明:软件版本为MongoDB(1.6.5),PECL Mongo(1.1.4)。不同版本结论可能不同。

PHP 相关文章推荐
如何在PHP中使用Oracle数据库(5)
Oct 09 PHP
修改Zend引擎实现PHP源码加密的原理及实践
Apr 14 PHP
php实现利用phpexcel导出数据
Aug 24 PHP
PHP把数字转成人民币大写的函数分享
Jun 30 PHP
PHP中读取文件的8种方法和代码实例
Aug 05 PHP
php实现两表合并成新表并且有序排列的方法
Dec 05 PHP
用php守护另一个php进程的例子
Feb 13 PHP
php输入数据统一类实例
Feb 23 PHP
PHP贪婪算法解决0-1背包问题实例分析
Mar 23 PHP
详解PHP归并排序的实现
Oct 18 PHP
用php+ajax新建流程(请假、进货、出货等)
Jun 11 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
Jun 06 PHP
php HandlerSocket的使用
May 02 #PHP
深入理解PHP原理之错误抑制与内嵌HTML分析
May 02 #PHP
PHP错误抑制符(@)导致引用传参失败Bug的分析
May 02 #PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
May 02 #PHP
PHP中使用gettext来支持多语言的方法
May 02 #PHP
php中神奇的fastcgi_finish_request
May 02 #PHP
PHP开发不能违背的安全规则 过滤用户输入
May 01 #PHP
You might like
生成卡号php代码
2008/04/09 PHP
php中3des加密代码(完全与.net中的兼容)
2012/08/02 PHP
ThinkPHP的MVC开发机制实例解析
2014/08/23 PHP
Yii CDBCriteria常用方法实例小结
2017/01/19 PHP
PHP7.1实现的AES与RSA加密操作示例
2018/06/15 PHP
jcrop基本参数一览
2013/07/16 Javascript
js获取字符串最后一位方法汇总
2014/11/13 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法
2016/08/03 Javascript
JS模拟实现方法重载示例
2016/08/03 Javascript
react native实现往服务器上传网络图片的实例
2017/08/07 Javascript
基于nodejs实现微信支付功能
2017/12/20 NodeJs
小程序从手动埋点到自动埋点的实现方法
2019/01/24 Javascript
Layui数据表格 前后端json数据接收的方法
2019/09/19 Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
2019/10/11 Javascript
[01:12]快闪回顾DOTA2亚洲邀请赛(DAC) 静候2018新征程开启
2018/03/11 DOTA
[00:13]天涯墨客二技能展示
2018/08/25 DOTA
python单线程实现多个定时器示例
2014/03/30 Python
使用Python求解最大公约数的实现方法
2015/08/20 Python
Python生成器定义与简单用法实例分析
2018/04/30 Python
python机器学习库xgboost的使用
2020/01/20 Python
基于SpringBoot构造器注入循环依赖及解决方式
2020/04/26 Python
Python实现打包成库供别的模块调用
2020/07/13 Python
一款利用纯css3实现的360度翻转按钮的实例教程
2014/11/05 HTML / CSS
CSS3 2D模拟实现摩天轮旋转效果
2016/11/16 HTML / CSS
HTML5中的音频和视频媒体播放元素小结
2016/01/29 HTML / CSS
高品质和独特的产品世界:Creations and Collections
2018/01/07 全球购物
护士自我介绍信
2014/01/13 职场文书
航海技术专业毕业生推荐信
2014/07/09 职场文书
介绍信范文
2015/01/31 职场文书
再见,2019我们不负使命;你好,2020我们砥砺前行
2020/01/03 职场文书
MySQL主从复制断开的常用修复方法
2021/04/07 MySQL
深入详解JS函数的柯里化
2021/06/09 Javascript
js中Object.create实例用法详解
2021/10/05 Javascript
解析mybatis-plus中的resultMap简单使用
2021/11/23 Java/Android
css实现左上角飘带效果的完整代码
2022/03/18 HTML / CSS