2010-07-20 10 views
10

J'utilise un Mongo MapReduce pour effectuer une opération de comptage de mots sur un tas de documents. Les documents sont très simples (juste un identifiant et un hachage de mots):MongoDB MapReduce ne renvoyant aucune donnée en 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 } } 

La base de données est appelée « mots » dans mon environnement, les collections en question sont nommées « wordsX » où X est un numéro de catégorie (Je sais, ne demande pas). Le champ dans le document hash où les mots sont stockés est également appelé "mots". Gah.

Le problème que j'ai est que dans certaines conditions dans mon application PHP, MapReduce ne renvoie aucune donnée. Généreusement, exécuter les mêmes commandes de la coque Mongo donne des résultats parfaits. J'essaie de savoir où ce bug se produit, mais je suis vraiment perplexe, alors j'espère que quelqu'un sera capable de faire la lumière là-dessus. Les préparatifs de cette question se poursuivent un peu, parce que l'environnement est un peu compliqué, mais s'il vous plaît, gardez-moi.

Les commandes que j'ai essayé de courir à partir du shell mongo pour répliquer les opérations en PHP sont les suivantes:

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] } } }); 

Il en résulte une collection temporaire en cours de création contenant les données de comptage de mots. Tout va bien jusqu'ici.

Cependant, si j'exécute les mêmes commandes depuis PHP (en utilisant la bibliothèque Mongo standard), je ne reçois aucune donnée dans certaines conditions. C'est un peu difficile à décrire parce que je ne veux pas vous ennuyer avec les détails de l'application/environnement au-delà de Mongo, mais en fait j'utilise Sphinx pour filtrer certains enregistrements, puis fournir une liste d'ID de contenu à Mongo. MapReduce est effectuée. Si je filtre dans l'ensemble de données de 2 ou 3 jours, je reçois des résultats de Mongo; Si je ne filtre pas, je récupère un jeu de données vide. Le code PHP pour exécuter la même opération est le suivant. Je n'ai pas inclus les parties basées sur Sphinx car je ne pense pas qu'elles soient pertinentes (sachez que nous obtenons une liste d'ID) parce que j'ai essayé de fournir exactement la même liste à Mongo en ligne de commande et j'ai obtenu les bons résultats, alors que je ne le fais pas depuis PHP. J'espère que cela a du sens.

Le code PHP J'utilise ressemble à ceci:

$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); 

Le contenu du tableau-info résultat ($arrStatsInfo) en conditions de travail et non-travail (le filtrage comme indiqué ci-dessus) sont les suivantes .

Résultats de travail:

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) 
} 

résultats vides:

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) 
} 

il ressemble à la condition brisée, aucun enregistrement font même dans le MapReduce. J'ai passé des heures à essayer de comprendre ce qui se passe ici, mais je n'ai pas eu d'idée jusqu'ici. Comme je l'ai dit, exécuter les mêmes commandes (comme ci-dessus) directement dans la ligne de commande Mongo en utilisant exactement le même jeu d'ID renvoie les bons résultats. Après tout cela, je suppose que ma question est la suivante: y a-t-il quelque chose qui cloche avec l'interaction PHP-Mongo que je fais ci-dessus? Y a-t-il d'autres mesures que je peux prendre pour essayer de déboguer cela?

S'il vous plaît laissez-moi savoir si le fournir des informations supplémentaires seraient utiles. J'apprécie que ce soit une question un peu expansive et mal définie, mais j'ai fait de mon mieux pour communiquer le problème! Espérons vraiment que quelqu'un puisse suggérer un moyen de s'en sortir.

Un grand merci pour votre lecture!

+3

Il s'avère que ce comportement bogué était en réalité (surprise surprise) un résultat de code ailleurs dans l'application. Nous avions deux routines pour insérer des documents dans la base de données; l'un a couru dans un lot énorme et l'autre a couru progressivement. L'une utilisait des chaînes numériques comme ID, et l'autre utilisait des entiers. Ils ont regardé la même chose d'un coup d'oeil, mais ont en fait créé des documents différents! Nous avons maintenant utilisé un int explicite partout (comme nous aurions dû le faire à l'origine, bien sûr) et tout va bien maintenant. Donc, la morale de l'histoire est, soyez très sûr que vous pouvez faire la différence entre les ints et les chaînes numériques! :) – BigglesZX

+0

Ceci n'est pas une réponse directe à votre question, mais je vous suggère de demander sur la liste [mongodb-user] (http://groups.google.com/group/mongodb-user?hl=fr) - - Cela peut être un bug dans les liens de la bibliothèque PHP, et le personnel de MongoDB répond généralement rapidement aux questions et aux rapports de bogues. Cette liste est plus susceptible de vous donner de l'aide que de poster sur ce site, à mon humble avis. –

+1

Ouch, j'aurais aimé lire cela avant de lire votre code - c'était ma conjecture, cependant. :) Vous devriez probablement voter pour fermer votre question, ou y répondre vous-même. –

Répondre

0

Pour les futurs lecteurs, ce problème s'est avéré être le résultat d'une gestion incohérente des chaînes ints/numériques ailleurs dans l'application. Désolé pour le hareng rouge!