2010-07-20 74 views
10

我正在使用Mongo MapReduce對一堆文檔執行字數統計操作。這些文件是非常簡單(只需一個ID和文字的哈希):MongoDB MapReduce不返回PHP中的數據

{ "_id" : 6714078, "words" : { "my" : 1, "cat" : 1, "john" : 1, "likes" : 1, "cakes" : 1 } } 
{ "_id" : 6715298, "words" : { "jeremy" : 1, "kicked" : 1, "the" : 1, "ball" : 1 } } 
{ "_id" : 6717695, "words" : { "dogs" : 1, "can't" : 1, "look" : 1, "up" : 1 } } 

的數據庫稱爲在我的環境,有問題的集合被命名爲「wordsX」,其中X是一個類別號碼(「詞」我知道,不要問)。文檔散列中存儲單詞的字段也稱爲「單詞」。嘎。

我遇到的問題是,在我的PHP應用程序的某些條件下,MapReduce不會返回任何數據。令人煩惱的是,從Mongo shell運行相同的命令給出了完美的結果。我試圖找出發生這種錯誤的位置,但我真的很難過,所以希望有人能夠闡明這一點。這個問題的引導確實有點過分,因爲環境有點複雜,但請耐心等待。是

我試着從蒙戈shell中運行復制基於PHP的操作的命令如下:

m = function() { 
    if (this.words) { 
     for (index in this.words) { 
      emit(index, this.words[index]); 
     } 
    } 
} 
r = function (key, values) { 
    var total = 0; 
    for (var i in values) { 
     total += values[i]; 
    } 
    return total; 
} 
res = db.words.mapReduce(m, r, { query : { _id : { $in : [6714078,6715298,6717695] } } }); 

這導致臨時集合包含字數數據被創建。到目前爲止,一切OK。

但是,如果我從PHP(使用標準的Mongo庫)運行相同的命令,我最終沒有在某些條件下的數據。描述有點棘手,因爲我不想讓你知道Mongo之外的應用程序/環境的細節,但基本上我使用Sphinx來過濾一些記錄,然後向Mongo提供一個內容ID列表, MapReduce被執行。如果我過濾2到3天的數據集,我會從Mongo獲得結果;如果我不過濾,我會返回一個空數據集。運行相同操作的PHP代碼如下。我沒有包含基於Sphinx的部分,因爲我不認爲它們是相關的(只知道我們得到了一個ID列表),因爲我已經嘗試在命令行上向Mongo提供完全相同的列表,並獲得了正確的結果,而我不從PHP內。希望這是有道理的。

PHP代碼我使用看起來像這樣:

$objMongo = new Mongo(); 
$objDB = $objMongo->words; 

$arrWordList = array(); 

$strMap = ' 
    function() { 
     if (this.words) { 
      for (index in this.words) { 
       emit(index, this.words[index]); 
      } 
     } 
    } 
'; 

$strReduce = ' 
    function(key, values) { 
     var total = 0; 
     for (var i in values) { 
      total += values[i]; 
     } 
     return total; 
    } 
'; 

$objMapFunc = new MongoCode($strMap); 
$objReduceFunc = new MongoCode($strReduce); 
$arrQuery = array(
    '_id' => array('$in' => $arrIDs) // <--- list of IDs from Sphinx 
); 
$arrCommand = array(
    'mapreduce' => 'wordsX', 
    'map' => $objMapFunc, 
    'reduce' => $objReduceFunc, 
    'query' => $arrQuery 
); 

MongoCursor::$timeout = -1; 

$arrStatsInfo = $objDB->command($arrCommand); 

var_dump($arrStatsInfo); 

結果-信息陣列($arrStatsInfo)的內容下工作和非工作條件(如上面指定的過濾)如下。

工作結果:

array(4) { 
    ["result"]=> 
    string(31) "tmp.mr.mapreduce_1279637336_227" 
    ["timeMillis"]=> 
    int(171) 
    ["counts"]=> 
    array(3) { 
    ["input"]=> 
    int(54) 
    ["emit"]=> 
    int(2517) 
    ["output"]=> 
    int(1526) 
    } 
    ["ok"]=> 
    float(1) 
} 

空的結果:

array(4) { 
    ["result"]=> 
    string(31) "tmp.mr.mapreduce_1279637381_228" 
    ["timeMillis"]=> 
    int(21) 
    ["counts"]=> 
    array(3) { 
    ["input"]=> 
    int(0) 
    ["emit"]=> 
    int(0) 
    ["output"]=> 
    int(0) 
    } 
    ["ok"]=> 
    float(1) 
} 

所以它看起來像破碎的條件下,沒有記錄,甚至使之成爲MapReduce的。我花了很多時間試圖弄清楚到底發生了什麼,但迄今爲止我還沒有發現任何見解。正如我所說的,使用完全相同的ID集合直接在Mongo命令行中運行相同的命令(如上所述)會返回正確的結果。

畢竟,我想我的問題是:是否有任何明顯的錯誤與我在上面做的PHP Mongo交互?我可以採取其他措施來嘗試調試嗎?

請讓我知道,如果提供任何進一步的信息將有所幫助。我很欣賞這是一個有點膨脹和不明確的問題,但我盡我所能來溝通這個問題!真的希望有人能提出一個解決方法。

非常感謝您的閱讀!

+3

事實證明,這個bug的行爲實際上是(驚喜)應用程序中其他地方代碼的結果。我們有兩個例程來將文件插入數據庫;一個跑了一大批,另一個跑得很快。一個使用數字字符串作爲ID,另一個使用整數。他們一目瞭然,但事實上創造了不同的文件!我們現在已經在任何地方都使用了明確的int投射(當然,我們原本應該這樣做),現在一切正常。 故事的寓意是,非常肯定你可以區分整數和數字字符串! :) – BigglesZX 2010-07-21 13:58:06

+0

這不是對您的問題的直接回答,但我建議您嘗試詢問[mongodb用戶](http://groups.google.com/group/mongodb-user?hl=en)列表 - - 它可能是PHP庫綁定中的一個錯誤,MongoDB工作人員通常會快速響應問題和錯誤報告。該列表更有可能爲您提供幫助,而不是在本網站發佈,恕我直言。 – 2010-07-20 15:23:56

+1

哎唷,希望在閱讀完代碼之前閱讀,但這是我的猜測。 :)你應該投票結束你的問題,或自己回答。 – 2012-08-15 01:30:54

回答

0

對於未來的讀者,這個問題原來是由於應用程序中其他地方的ints/numeric字符串處理不一致造成的。對不起,關於紅鯡魚!