我正在使用Mongo MapReduce对一堆文档执行字数统计操作.文档非常简单(只是一个ID和一个单词的哈希):
{ "_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运行相同的命令可以获得完美的结果.我正试图确定这个错误发生的地方,但我真的很难过,所以希望有人能够对此有所了解.这个问题的前言确实有点过了,因为环境有点复杂,但请耐心等待.
我尝试从Mongo 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] } } });
这会导致创建包含单词计数数据的临时集合.到目前为止一切都好.
但是,如果我从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
工作和非工作条件下的result-info数组()的内容(如上所述的过滤)如下所示.
工作成果:
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交互有什么明显的错误吗?我可以采取其他步骤来尝试调试吗?
如果提供任何进一步的信息会有所帮助,请告诉我.我很欣赏这是一个有点广泛和定义不明确的问题,但我已尽力传达这个问题!真的希望有人能提出解决方法.
非常感谢您的阅读!