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如何编写易读的代码
Jul 10 PHP
zend optimizer在wamp的基础上安装图文教程
Oct 26 PHP
ThinkPHP调试模式与日志记录概述
Aug 22 PHP
PHP连接SQLServer2005的方法
Jan 27 PHP
php通过正则表达式记取数据来读取xml的方法
Mar 09 PHP
php实现用于删除整个目录的递归函数
Mar 16 PHP
php实现在限定区域里自动调整字体大小的类实例
Apr 02 PHP
PHP获取文件行数的方法
Jun 10 PHP
thinkPHP的表达式查询用法详解
Sep 14 PHP
PHP编译configure时常见错误的总结
Aug 17 PHP
PHP实现的只保留字符串首尾字符功能示例【隐藏部分字符串】
Mar 11 PHP
PHP Web表单生成器案例分析
Jun 02 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.ini中文版(1)
2006/10/09 PHP
几种有用的变型 PHP中循环语句的用法介绍
2012/01/30 PHP
深入理解require与require_once与include以及include_once的区别
2013/06/05 PHP
php中3种方法删除字符串中间的空格
2014/03/10 PHP
使用ThinkPHP+Uploadify实现图片上传功能
2014/06/26 PHP
Laravel下生成验证码的类
2017/11/15 PHP
js使用数组判断提交数据是否存在相同数据
2013/11/27 Javascript
详解JavaScript的变量和数据类型
2015/11/27 Javascript
javascript瀑布流布局实现方法详解
2016/02/17 Javascript
纯js实现瀑布流布局及ajax动态新增数据
2016/04/07 Javascript
Vue.js基础知识汇总
2016/04/27 Javascript
深入解析桶排序算法及Node.js上JavaScript的代码实现
2016/07/06 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
本地存储localStorage用法详解
2017/07/31 Javascript
详解JS模块导入导出
2017/12/20 Javascript
小程序扫描普通链接二维码跳转小程序指定界面方法
2019/05/07 Javascript
node.js的http.createServer过程深入解析
2019/06/06 Javascript
微信小程序scroll-view隐藏滚动条的方法详解
2020/03/25 Javascript
Vue + Element-ui的下拉框el-select获取额外参数详解
2020/08/14 Javascript
机器学习的框架偏向于Python的13个原因
2017/12/07 Python
利用python为运维人员写一个监控脚本
2018/03/25 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
Django添加sitemap的方法示例
2018/08/06 Python
python http基本验证方法
2018/12/26 Python
详解用python生成随机数的几种方法
2019/08/04 Python
Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
2020/01/13 Python
python游戏开发的五个案例分享
2020/03/09 Python
解决Django中checkbox复选框的传值问题
2020/03/31 Python
Python Opencv轮廓常用操作代码实例解析
2020/09/01 Python
印度民族服装购物网站:BIBA
2019/08/05 全球购物
数据库测试通常都包括哪些方面
2015/11/30 面试题
材料工程专业毕业生求职信
2014/03/04 职场文书
财产分割协议书
2016/03/22 职场文书
MySQL COUNT函数的使用与优化
2021/05/10 MySQL
JavaScript流程控制(循环)
2021/12/06 Javascript
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android