MongoDB MapReduce在PHP中不返回任何数据

时间:2010-07-20 15:07:23

标签: php mongodb mapreduce

我正在使用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交互有什么明显的错误吗?我可以采取其他步骤来尝试调试吗?

如果提供任何进一步的信息会有所帮助,请告诉我。我很欣赏这是一个有点广泛和定义不明确的问题,但我已尽力传达这个问题!真的希望有人可以提出解决方法。

非常感谢您的阅读!

1 个答案:

答案 0 :(得分:0)

对于未来的读者来说,这个问题结果是应用程序中其他地方的整数/数字字符串处理不一致的结果。抱歉红鲱鱼!