我正在使用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交互?我可以採取其他措施來嘗試調試嗎?
請讓我知道,如果提供任何進一步的信息將有所幫助。我很欣賞這是一個有點膨脹和不明確的問題,但我盡我所能來溝通這個問題!真的希望有人能提出一個解決方法。
非常感謝您的閱讀!
事實證明,這個bug的行爲實際上是(驚喜)應用程序中其他地方代碼的結果。我們有兩個例程來將文件插入數據庫;一個跑了一大批,另一個跑得很快。一個使用數字字符串作爲ID,另一個使用整數。他們一目瞭然,但事實上創造了不同的文件!我們現在已經在任何地方都使用了明確的int投射(當然,我們原本應該這樣做),現在一切正常。 故事的寓意是,非常肯定你可以區分整數和數字字符串! :) – BigglesZX 2010-07-21 13:58:06
這不是對您的問題的直接回答,但我建議您嘗試詢問[mongodb用戶](http://groups.google.com/group/mongodb-user?hl=en)列表 - - 它可能是PHP庫綁定中的一個錯誤,MongoDB工作人員通常會快速響應問題和錯誤報告。該列表更有可能爲您提供幫助,而不是在本網站發佈,恕我直言。 – 2010-07-20 15:23:56
哎唷,希望在閱讀完代碼之前閱讀,但這是我的猜測。 :)你應該投票結束你的問題,或自己回答。 – 2012-08-15 01:30:54