我正在使用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);
在工作和非工作条件下(上面指定的过滤)的result-info数组($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交互有什么明显的错误吗?我可以采取其他步骤来尝试调试吗?
如果提供任何进一步的信息会有所帮助,请告诉我。我很欣赏这是一个有点广泛和定义不明确的问题,但我已尽力传达这个问题!真的希望有人可以提出解决方法。
非常感谢您的阅读!
答案 0 :(得分:0)
对于未来的读者来说,这个问题结果是应用程序中其他地方的整数/数字字符串处理不一致的结果。抱歉红鲱鱼!