2012-06-28 7 views
0

J'ai plusieurs modèles Mongoid sur lesquels je lance mapreduce, et je voudrais stocker les résultats unifiés dans une seule collection daily_stats. Ma carte & réduire les fonctions fonctionnent très bien pour les 3 modèles, mais même lors de la sortie via collection.mapreduce(map, reduce, {:out => "daily_stats", :raw => true}), les résultats de la carte ultérieure réduire les opérations écrasent les résultats précédents, même ce qu'ils n'ont pas les clés qui se chevauchent:Collection de résultats mapreduce partagés dans MongoDB

{'_id': "2012-06-01", 'values': {photos: 10}} 
{'_id': "2012-06-02", 'values': {photos: 10}} 

Valeurs pour photos se jeter quand une passe ultérieure retourne:

{'_id': "2012-06-01", 'values': {comments: 1}} 
{'_id': "2012-06-02", 'values': {comments: 6}} 

J'ai essayé de fusionner aussi avec collection.mapreduce(map, reduce, {:out => {:merge => "daily_stats"}, :raw => true}), mais cela ne semble pas fonctionner non plus.

Des idées?

MISE À JOUR

La carte & réduire les fonctions sont comme ça pour chaque modèle:

Carte:

function() { 
    day = Date.UTC(this.created_at.getFullYear(), this.created_at.getMonth(), this.created_at.getDate()); 
    emit(day, {users: 1}); 
    }; 

Réduire: fonction (clés, valeurs) { var users_added_count = 0;

values.forEach(function(v) { 
     users_added_count += parseInt(v['users']) || 0; 
    }); 

    return {users: users_added_count}; 
    } 

Voici quelques informations supplémentaires sur le schéma résultant:

{ "_id" : 1337040000000, 
"value" : { 
    "apartments" : 280, 
    "price" : 1003653, 
    "photos" : 83, 
    "comments" : 0 } 
} 
+0

Y at-il une raison quelconque vous ne l'avez pas et/ou ne pouvez pas exécuter carte une fois réduire et émette un seul document, à savoir: emit (jour, {utilisateurs: 1}, {photos: 1}, {commentaires: 1})? – Jenna

+0

Oh, je vois. Vous avez initialement trois collections distinctes: une pour les utilisateurs, les photos et les commentaires? Je vais écrire un exemple pour illustrer un moyen de fusionner les données. – Jenna

+0

Ou est le document du "schéma résultant" votre modèle de données d'entrée? Désolé, pour clarifier, pouvez-vous fournir plus d'exemples de vos données? – Jenna

Répondre

1

Si vous regardez la documentation MongoDB pour carte réduire (http://www.mongodb.org/display/DOCS/MapReduce# MapReduce-Outputoptions), vous verrez que par défaut, la collection de sortie MR remplace toutes les collections existantes avec le même nom. "Fusionner" ajoute de nouvelles données dans l'ancienne collection de sortie, mais écrase les documents avec la même clé.

Il semble que votre clé soit la date? Si

{'_id': "2012-06-01", 'values': {photos: 10}} 

et

{'_id': "2012-06-01", 'values': {comments: 1}} 

ont la même clé, le deuxième document remplacera le premier lorsque vous exécutez MR. Vous devez spécifier une clé plus unique, ou vous devez avoir plusieurs collections de sortie (peut-être une pour les photos et une pour les commentaires?).

+0

Correct, la clé est la date. Il n'y a aucun moyen de fusionner des éléments avec la même clé? Un peu comme '$ addToSet' fait pour les champs de tableau? – Avishai

+0

Étant donné que chaque document doit avoir un champ _id unique (afin de créer un index unique sur le document et garder une trace de l'emplacement du document), il n'est pas possible de fusionner des documents avec la même clé; Cependant, je pense qu'il existe une solution à votre problème impliquant la fonction de finalisation dans la carte réduire. Si vous fournissez des informations supplémentaires sur vos fonctions MR et votre schéma de données, je peux vous aider. – Jenna

+0

Bien sûr, j'ai ajouté ma carte et réduire pour les utilisateurs. Les autres modèles sont à peu près les mêmes. – Avishai

0

Vous pouvez émettre avec une clé de hachage pour le rendre unique sur vos modèles

emit({day: day, type: '<model class name>'}, 1); 
Questions connexes