PHP驱动MongoDB整数问题的BUG和策略

本文所说的整数问题,其实并不是MongoDB的问题,而是PHP驱动的问题: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)。不同版本结论可能不同。

时间: 2025-01-20 20:11:13

PHP驱动MongoDB整数问题的BUG和策略的相关文章

【Mongodb】Replica Set 的选举策略之三

承接之前的文章继续介绍replica set 选举机制. 创建两节点的Replica Sets,一主一备secondary,如果Secondary宕机,Primary会变成Secondary!这时候集群里没有Primary了!为什么会出现这样的情况呢. [mongodb@rac4 bin]$ mongo 127.0.0.1:27018 init1node.js  MongoDB shell version: 2.0.1 connecting to: 127.0.0.1:27018/test [m

【Mongodb】 Replica set 的 选举策略之二

对于Replica Set中的选择策略: We use a consensus protocol to pick a primary. Exact details will be spared here but that basic process is: 1 get maxLocalOpOrdinal from each server. 2 if a majority of servers are not up (from this server's POV), remain in Secon

受消费市场驱动、互联网与传统经济融合等策略是主因

网友"横竖撇捺":麦肯锡全球研究院近日发布了一份报告,称中国互联网经济占GDP的比重不断上升,已经超越了美国.是这样吗?腾讯科技:麦肯锡全球研究院近日发布了<中国的数字化转型:互联网对生产力与增长的影响>报告,提出了iGDP的概念,即互联网经济占GDP的比重.报告认为,2010年,中国的互联网经济只占GDP的比例为3.3%,落后于大多数发达国家.而到了2013年,中国的iGDP指数升至4.4%,已经达到全球领先国家的水平.根据该报告,中国互联网经济成功崛起反超美国的原因包括

【Mongodb】 Replica set 的选举策略之一

首先介绍一下在replica set里分为三种节点类型: 1 primary   负责client的读写. 2 secondary 作为热备节点,应用Primary的oplog读取的操作日志,和primary保持一致,不提供读写操作!   secondary有两种类型:    1)normal secondary   随时和Primay保持同步,     2)delayed secondary  延时指定时间和primary保持同步,防止误操作.  3 arbiter.它不负责任何读写,只作为一

软件测试bug收集策略

Error = 0 的程序是不存在的,怎样收集和处理程序中的错误?怎样更好地利用错误信息的收集和反馈来协助程序的调试?怎样让产品发布后,用户能够反馈出更有价值的问题 信息?这些问题是本文将要涉及的,最近对自己所做项目中的错误处理机制做了一些总结与思考,故在此讨论,希望对大家有所帮助. 目前,按照我个人的理解,软件中的错误收集和反馈方式主要有如下几种: 第一种方式:使用常用的信息输出语句. 对于控制台程序,可以使用 printf 语句或者 std::cout 将错误信息打印出来:对于MFC程序,可

MongoDB学习笔记(二) 通过samus驱动实现基本数据操作

传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由 (database).集合(collection).文档对象(document)三个层次组成.MongoDB对于关系型数据库里的表,但是集合中没 有列.行和关系概念,这体现了模式自由的特点. 一.关于MongoDB的驱动 MongoDB 支持多种语言的驱动,在此我们只介绍C#的驱动.仅C#驱动都有很多种,每种驱动的形式大致相同,但是细节各有千秋,因此代码不能通用.比较常用

MongoDB学习笔记(二) 通过samus驱动实现基本数据操作_服务器其它

传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由(database).集合(collection).文档对象(document)三个层次组成.MongoDB对于关系型数据库里的表,但是集合中没有列.行和关系概念,这体现了模式自由的特点. 一.关于MongoDB的驱动 MongoDB支持多种语言的驱动,在此我们只介绍C#的驱动.仅C#驱动都有很多种,每种驱动的形式大致相同,但是细节各有千秋,因此代码不能通用.比较常用的是官

mongodb学习笔记-tina

mongodb mongodb是面向文档的数据库,不是关系型数据库.基本思路是将原来的"行row" 概念换成更加灵活的"文档"document模型.  关于MongoDB的好处,优点之类的这里就不说了,唯一要讲的一点就是MongoDB中有三元素:数据库,集合,文档,其中"集合"就是对应关系数据库中的"表","文档"对应"行". --- [root@viptest2 bin]# ll mo

驱动精灵发布升级扩展版内置网卡驱动包

距上个版本的驱动精灵发布已一月有余,在这段时间里,我们努力收集了一些细节问题,在这次的驱动精灵2011 SP3版本中进行了修正和改进.我们着手解决了Windows 7以上非中文操作系统驱动列表存在乱码的问题.之前有部分用户反馈在非中文系统下使用驱动精灵可能会遇到乱码的麻烦,这次改进之后,这些问题已经得到解决. 其次,我们对驱动微调部分进行了很多细节改动,新增了一键安装驱动按钮,用户可以一次性升级需安装的驱动程序.同时,我们这次新增了实用的驱动回滚功能. 至于驱动管理中的部分Bug,我们也在这个版