PHP操作MongoDB时的整数问题及对策说明

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的对应关系:

SQL to MongoDB

此外,还有很多资料可供参考,如:MongoDB Aggregation III: Map-Reduce Basics

说明:软件版本为MongoDB(1.6.5),PECL Mongo(1.1.4)。不同版本结论可能不同。

(0)

相关推荐

  • 深入PHP操作MongoDB的技术总结

    复制代码 代码如下: <?php/*** PHP操作MongoDB学习笔记*///*************************//**   连接MongoDB数据库  **////*************************//格式=>("mongodb://用户名:密码 @地址:端口/默认指定数据库",参数)$conn = new Mongo();//可以简写为//$conn=new Mongo(); #连接本地主机,默认端口.//$conn=new Mong

  • 在MongoDB中模拟Auto Increment的php代码

    代码大致如下所示: 复制代码 代码如下: <?php function generate_auto_increment_id($namespace, array $option = array()) { $option += array( 'init' => 1, 'step' => 1, ); $instance = new Mongo(); $instance = $instance->selectCollection('_seq', 'seq'); $seq = $insta

  • php对mongodb的扩展(初出茅庐)

    我们的php mongodb也能做mysql.sqlserver能做的几乎所有功能,本文将详细介绍 一.操作符 操作符相信大家肯定都知道了,就是等于.大于.小于.不等于.大于等于.小于等于,但是在mongodb里不能直接使用这些操作符.在mongodb里的操作符是这样表示的: (1) $gt > (大于) (2) $lt < (小于) (3) $gte >= (大于等于) (4) $lt <= (小于等于) (5) $ne != (不等于) (6) $in in (包含) (7)

  • 解析:使用php mongodb扩展时 需要注意的事项

    最近在使用php的mongo 扩展进行数据统计计算,其中有一个时间戳字段,由于精确到了毫秒,长度有13位,但由于开始的时候是以字符串的形式存储: 复制代码 代码如下: { "_id" : ObjectId("504eea97e4b023cf38e34039"), "in_ts" : NumberLong("1347349143699"), "log" : { "guid" : "

  • PHP与MongoDB简介|安全|M+PHP应用实例详解

    一.MongoDB简介MongoDB (名称来自"humongous") 是一个可扩展的.高性能.开源.模式自由.面向文档的数据库,集文档数据库.键值对存储和关系型数据库的优点于一身.官方站点:http://www.mongodb.org/,MongoDB特点: •面向文档存储(类JSON数据模式简单而强大)•动态查询•全索引支持,扩展到内部对象和内嵌数组•查询记录分析•快速,就地更新•高效存储二进制大对象 (比如照片和视频)•复制和故障切换支持•Auto-Sharding自动分片支持

  • php对mongodb的扩展(小试牛刀)

    今天外面刮着呼呼的大风,能在一个温暖的小屋写着博客也是北漂的一种幸福.好了废话不多说,今天主要说一下php连接.操作mongodb,如果你没有看上两期的内容,不知道如何安装php对mongodb的扩展的话请您返回去看<php对mongodb的扩展(初识如故) >和<php对mongodb的扩展(初出茅庐)> . php 连接mongodb 复制代码 代码如下: try { $mongo = new Mongo("mongodb://username:password@12

  • PHP对MongoDB[NoSQL]数据库的操作

    一.MongoDB简介 MongoDB (名称来自"humongous") 是一个可扩展的.高性能.开源.模式自由.面向文档的数据库,集文档数据库.键值对存储和关系型数据库的优点于一身.官方站点:http://www.mongodb.org/,MongoDB特点: •面向文档存储(类JSON数据模式简单而强大)•动态查询•全索引支持,扩展到内部对象和内嵌数组•查询记录分析•快速,就地更新•高效存储二进制大对象 (比如照片和视频)•复制和故障切换支持•Auto-Sharding自动分片支

  • php对mongodb的扩展(初识如故)

    在博主的威逼之下特为大家进行一下小分享,特此申明博主人品非常淳朴只是威逼,绝对没有利诱. 由于mongodb的相关中文资料较少,之后若有机会继续为大家分享.希望这点小分享能给大家带来收获,言归正传请往下看. 为什么说"初识如故"呢,因为mongodb的数据存储格式是一种由于MongoDB的文档结构为BJSON格式(BJSON全称:BinaryJSON),而BJSON格式本身就支持保存二进制格式的数据,因此可以把文件的二进制格式的数据直接保存到MongoDB的文档结构中. MongoDB

  • 作为PHP程序员应该了解MongoDB的五件事

    2010年应该被人们记住,因为SQL将在这一年死去.这一年关系数据库行将就木,这一年开发者发现他们再不需要长时间辛苦的构造列或者表格来存放数据.2010年将是文档型数据库的起始年.尽管这样的势头已经持续多年,现在才是一个更多,更广泛的文档型数据库出现的年代.从基于云计算的Amazon到Google,大量开源工具,以及随之诞生的CouchDB和MongoDB.那么什么是MongoDB?下面有五件事是PHP开发者应该了解的:1. MongoDB是一个单独的服务器;2. MongoDB是基于文档,而不

  • PHP连接MongoDB示例代码

    复制代码 代码如下: <?php //这里采用默认连接本机的27017端口,当然你也可以连接远程主机如192.168.0.4:27017,如果端口是27017,端口可以省略 $m = new Mongo(); // 选择comedy数据库,如果以前没该数据库会自动创建,也可以用$m->selectDB("comedy"); $db = $m->comedy; //选择comedy里面的collection集合,相当于RDBMS里面的表,也-可以使用 $collecti

随机推荐