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邮件专题
Oct 09 PHP
用PHP实现多服务器共享SESSION数据的方法
Mar 16 PHP
PHP连接MongoDB示例代码
Sep 06 PHP
php 判断数组是几维数组
Mar 20 PHP
不使用php api函数实现数组的交换排序示例
Apr 13 PHP
ThinkPHP跳转页success及error模板实例教程
Jul 17 PHP
列举PHP的Yii 2框架的开发优势
Jul 03 PHP
YII Framework教程之异常处理详解
Mar 14 PHP
全面解读PHP的Yii框架中的日志功能
Mar 17 PHP
php截取视频指定帧为图片
May 16 PHP
php使用Jpgraph创建折线图效果示例
Feb 15 PHP
如何在PHP中读写文件
Sep 07 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
神族 PROTOSS 概述
2020/03/14 星际争霸
用libTemplate实现静态网页的生成
2006/10/09 PHP
深入理解php printf() 输出格式化的字符串
2016/05/23 PHP
微信支付开发动态链接Native支付
2016/07/12 PHP
PHP重定向与伪静态区别
2017/02/19 PHP
用php定义一个数组最简单的方法
2019/10/04 PHP
javascript 保存文件到本地实现方法
2012/11/29 Javascript
jquery插件之定时查询待处理任务数量
2014/05/01 Javascript
jQuery中:not选择器用法实例
2014/12/30 Javascript
D3.js中强制异步文件读取同步的几种方法
2017/02/06 Javascript
360doc网站不登录就无法复制内容的解决方法
2018/01/27 Javascript
自定义vue组件发布到npm的方法
2018/05/09 Javascript
解决angular2 获取到的数据无法实时更新的问题
2018/08/31 Javascript
Vue.js构建你的第一个包并在NPM上发布的方法步骤
2019/05/01 Javascript
用js编写留言板
2020/03/17 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[43:53]OG vs EG 2019国际邀请赛淘汰赛 胜者组 BO3 第三场 8.22
2019/09/05 DOTA
学习python (1)
2006/10/31 Python
Python分析学校四六级过关情况
2017/11/22 Python
python opencv之分水岭算法示例
2018/02/24 Python
python批量爬取下载抖音视频
2019/06/17 Python
阿里云ECS服务器部署django的方法
2019/08/29 Python
Python 中使用 PyMySQL模块操作数据库的方法
2019/11/10 Python
Python更新所有已安装包的操作
2020/02/13 Python
Python MySQL 日期时间格式化作为参数的操作
2020/03/02 Python
Web前端页面跳转并取到值
2017/04/24 HTML / CSS
AHAVA美国官方网站:死海海泥护肤品牌
2016/10/18 全球购物
英国最受欢迎的母婴精品品牌:JoJo Maman BéBé
2021/02/17 全球购物
教师自荐书
2013/10/08 职场文书
绩效考核实施方案
2014/03/18 职场文书
领导班子四风表现材料
2014/08/23 职场文书
护理工作个人总结
2015/03/03 职场文书
反邪教观后感
2015/06/11 职场文书
SpringBoot整合MongoDB的实现步骤
2021/06/23 MongoDB
纯html+css实现Element loading效果
2021/08/02 HTML / CSS
Golang原生rpc(rpc服务端源码解读)
2022/04/07 Golang