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 相关文章推荐
理解PHP5中static和const关键字的区别
Mar 19 PHP
PHP实现定时生成HTML网站首页实例代码
Nov 20 PHP
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同之处小结
Mar 07 PHP
php中flush()、ob_flush()、ob_end_flush()的区别介绍
Feb 17 PHP
基于PHP CURL获取邮箱地址的详解
Jun 03 PHP
Linux Apache PHP Oracle 安装配置(具体操作步骤)
Jun 17 PHP
解析PHP实现下载文件的两种方法
Jul 05 PHP
PHP5中实现多态的两种方法实例分享
Apr 21 PHP
Thinkphp调用Image类生成缩略图的方法
Mar 07 PHP
PHP获取二维数组中某一列的值集合
Dec 25 PHP
PHP+MySQL存储数据常见中文乱码问题小结
Jun 13 PHP
PHP之多条件混合筛选功能的实现方法
Oct 09 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获取网络文件的实现代码
2010/01/01 PHP
php页面缓存ob系列函数介绍
2012/10/18 PHP
PHP5常用函数列表(分享)
2013/06/07 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
laravel框架select2多选插件初始化默认选中项操作示例
2020/02/18 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
通过隐藏option实现select的联动效果
2009/11/10 Javascript
用js调用迅雷下载代码的二种方法
2013/04/15 Javascript
javascript数组操作(创建、元素删除、数组的拷贝)
2014/04/07 Javascript
jQuery中data()方法用法实例
2014/12/27 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
微信公众号-获取用户信息(网页授权获取)实现步骤
2016/10/21 Javascript
js下载文件并修改文件名
2017/05/08 Javascript
微信小程序中页面FOR循环和嵌套循环
2017/06/21 Javascript
Vue 父子组件的数据传递、修改和更新方法
2018/03/01 Javascript
vue动态设置页面title的方法实例
2020/08/23 Javascript
Python利用Nagios增加微信报警通知的功能
2016/02/18 Python
Python编写一个优美的下载器
2018/04/15 Python
python实现猜数字小游戏
2020/03/24 Python
浅谈python编译pyc工程--导包问题解决
2019/03/20 Python
python基于Selenium的web自动化框架
2019/07/14 Python
在macOS上搭建python环境的实现方法
2019/08/13 Python
Flask处理Web表单的实现方法
2021/01/31 Python
Python制作运行进度条的实现效果(代码运行不无聊)
2021/02/24 Python
HTML5边玩边学(3)像素和颜色
2010/09/21 HTML / CSS
美国知名玩具品牌:Melissa & Doug
2016/08/16 全球购物
新加坡第一的杂货零售商:NTUC FairPrice
2020/12/05 全球购物
实习生评语
2014/04/26 职场文书
2014领导班子专题民主生活会对照检查材料思想汇报
2014/09/23 职场文书
八年级上册语文教学计划
2015/01/22 职场文书
何玥事迹观后感
2015/06/16 职场文书
学校食堂管理制度
2015/08/04 职场文书
初二数学教学反思
2016/02/17 职场文书
一文彻底理解js原生语法prototype,__proto__和constructor
2021/10/24 Javascript
MySQL 数据类型详情
2021/11/11 MySQL
Arthas排查Kubernetes中应用频繁挂掉重启异常
2022/02/28 MySQL