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的知识
Nov 17 PHP
php cookie 作用范围?不要在当前页面使用你的cookie
Mar 24 PHP
PHP开启gzip页面压缩实例代码
Mar 11 PHP
PHP常用技巧总结(附函数代码)
Feb 04 PHP
调试PHP程序的多种方法介绍
Nov 06 PHP
php根据某字段对多维数组进行排序的方法
Mar 07 PHP
php字符串函数学习之substr()
Mar 27 PHP
详解WordPress中创建和添加过滤器的相关PHP函数
Dec 29 PHP
PHP正则删除HTML代码中宽高样式的方法
Jun 12 PHP
实例讲解YII2中多表关联的使用方法
Jul 21 PHP
php支付宝APP支付功能
Jul 29 PHP
laravel5.6中的外键约束示例
Oct 23 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修改session_id示例代码
2014/01/08 PHP
ThinkPHP结合ajax、Mysql实现的客户端通信功能代码示例
2014/06/23 PHP
CI框架(CodeIgniter)实现的数据库增删改查操作总结
2018/05/23 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
PHP从零开始打造自己的MVC框架之类的自动加载实现方法详解
2019/06/03 PHP
基于jQuery的图片大小自动适应实现代码
2010/11/17 Javascript
JavaScript初学者应注意的七个细节小结
2012/01/30 Javascript
JS文本框默认值处理详解
2013/07/10 Javascript
Javascript限制网页只能在微信内置浏览器中访问
2014/11/09 Javascript
表单验证正则表达式实例代码详解
2015/11/09 Javascript
jQuery 常用代码集锦(必看篇)
2016/05/16 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
2016/09/04 Javascript
IntersectionObserver API 详解篇
2016/12/11 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
vue实现样式之间的切换及vue动态样式的实现方法
2017/12/19 Javascript
微信小程序实现左右联动的实战记录
2018/07/05 Javascript
详解微信小程序input标签正则初体验
2018/08/18 Javascript
微信小程序中网络请求缓存的解决方法
2019/12/29 Javascript
Vue中fragment.js使用方法小结
2020/02/17 Javascript
vue 数据双向绑定的实现方法
2021/03/04 Vue.js
[58:58]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第二场
2018/04/05 DOTA
利用Fn.py库在Python中进行函数式编程
2015/04/22 Python
Python创建xml文件示例
2017/03/22 Python
python Spyder界面无法打开的解决方法
2018/04/27 Python
python中scikit-learn机器代码实例
2018/08/05 Python
Django实现微信小程序的登录验证功能并维护登录态
2019/07/04 Python
python实现DEM数据的阴影生成的方法
2019/07/23 Python
Python实用库 PrettyTable 学习笔记
2019/08/06 Python
自适应线性神经网络Adaline的python实现详解
2019/09/30 Python
使用python实现学生信息管理系统
2021/02/25 Python
英国最大的割草机购买网站:Just Lawnmowers
2019/11/02 全球购物
精选鞋类、服装和配饰的全球领先目的地:Bodega
2021/02/27 全球购物
测绘工程本科生求职信
2013/10/10 职场文书
儿子满月酒致辞
2015/07/29 职场文书
祝酒词范文
2015/08/12 职场文书
MySQL中一条update语句是如何执行的
2022/03/16 MySQL