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 中dirname(_file_)讲解
Mar 18 PHP
封装一个PDO数据库操作类代码
Sep 09 PHP
php 数组的指针操作实现代码
Feb 08 PHP
PHP在字符断点处截断文字的实现代码
Apr 21 PHP
php开发留言板的CRUD(增,删,改,查)操作
Apr 19 PHP
PHP+MYSQL会员系统的开发实例教程
Aug 23 PHP
php中字符集转换iconv函数使用总结
Oct 11 PHP
php实现可用于mysql,mssql,pg数据库操作类
Dec 13 PHP
smarty模板引擎中变量及变量修饰器用法实例
Jan 22 PHP
PHP 极验验证码实例讲解
Sep 29 PHP
PHP中类的自动加载的方法
Mar 17 PHP
PHP哈希表实现算法原理解析
Dec 11 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函数scandir排除特定目录
2014/06/12 PHP
CentOS7系统搭建LAMP及更新PHP版本操作详解
2020/03/26 PHP
优秀js开源框架-jQuery使用手册(1)
2007/03/10 Javascript
javascript 静态对象和构造函数的使用和公私问题
2010/03/02 Javascript
JS添加删除一组文本框并对输入信息加以验证判断其正确性
2013/04/11 Javascript
jQuery中odd选择器的定义和用法
2014/12/23 Javascript
jQuery中contents()方法用法实例
2015/01/08 Javascript
JQuery中的事件及动画用法实例
2015/01/26 Javascript
javascript中AJAX用法实例分析
2015/01/30 Javascript
jQuery选择器及jquery案例详解(必看)
2016/05/20 Javascript
全面解析标签页的切换方式
2016/08/21 Javascript
AngularJS 面试题集锦
2016/09/06 Javascript
javascript中的后退和刷新实现方法
2016/11/10 Javascript
js实现九宫格的随机颜色跳转
2017/02/19 Javascript
javascript DOM的详解及实例代码
2017/03/06 Javascript
浅谈Node.js之异步流控制
2017/10/25 Javascript
node.js读取Excel数据(下载图片)的方法示例
2018/08/02 Javascript
jQuery实现每日秒杀商品倒计时功能
2019/09/06 jQuery
Vue简单实现原理详解
2020/05/07 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
如何检测JavaScript中的死循环示例详解
2020/08/30 Javascript
python+ffmpeg视频并发直播压力测试
2018/03/06 Python
python自动发送测试报告邮件功能的实现
2019/01/22 Python
python3.7环境下安装Anaconda的教程图解
2019/09/10 Python
如何在mac下配置python虚拟环境
2020/07/06 Python
灵活运用CSS3特性绘制简易版围棋效果
2016/09/28 HTML / CSS
美国从事品牌鞋类零售的连锁店:Famous Footwear
2016/08/25 全球购物
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
阿根廷旅游网站:almundo阿根廷
2018/02/12 全球购物
Java如何读取CLOB字段
2013/10/10 面试题
2014年音乐教师工作总结
2014/12/03 职场文书
大学生国家助学金感谢信
2015/01/23 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
2015秋季开学典礼主持词
2015/07/16 职场文书
小学运动会加油词
2015/07/18 职场文书
中国古代史学名著《战国策》概述
2019/08/09 职场文书