MongoDB MapReduce не возвращает данных в PHP - PullRequest
10 голосов
/ 20 июля 2010

Я использую Mongo MapReduce для выполнения операции подсчета слов в пачке документов.Документы очень просты (просто идентификатор и хэш слов):

{ "_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 дает отличные результаты.Я пытаюсь определить, где происходит эта ошибка, но я действительно озадачен, так что надеюсь, что кто-то сможет пролить свет на это.Подготовка к этому вопросу продолжается, потому что среда немного сложна, но, пожалуйста, потерпите меня.

Команды, которые я пытался запустить из оболочки Mongo для репликации на основе 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, на которомMapReduce выполняется.Если я отфильтрую данные, заданные на 2 или 3 дня, я получу результаты от Монго;если я не фильтрую, я получаю пустой набор данных обратно.Код PHP для запуска той же операции выглядит следующим образом.Я не включил части на основе Sphinx, так как не думаю, что они актуальны (просто знаю, что мы получаем список идентификаторов), потому что я попытался передать точно такой же список 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.Я потратил целую вечность, пытаясь понять, что здесь происходит, но до сих пор у меня не было понимания.Как я уже сказал, выполнение тех же команд (как указано выше) непосредственно в командной строке Mongo с использованием точно такого же набора идентификаторов возвращает правильные результаты.

После всего этого я предполагаю, что мой вопрос: есть личто-то явно не так с взаимодействием PHP-Mongo, которое я делаю выше?Могу ли я предпринять другие шаги, чтобы попытаться отладить это?

Пожалуйста, дайте мне знать, если будет полезна дополнительная информация.Я ценю, что это довольно обширный и плохо определенный вопрос, но я изо всех сил старался донести эту проблему!Очень надеюсь, что кто-то может предложить выход из этого.

Большое спасибо за чтение!

1 Ответ

0 голосов
/ 16 августа 2012

Для будущих читателей эта проблема оказалась результатом несовместимой обработки целочисленных / числовых строк в других местах приложения. Извините за красную сельдь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...