PHP驅動MongoDB整數問題的BUG和策略

來源:互聯網
上載者:User

本文所說的整數問題,其實並不是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)。不同版本結論可能不同。



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.