2011-02-28 2 views
4

Recherche de fonctionnalités similaires à Distinct On de Postgres. Avoir une collection de documents {user_id, current_status, date}, où l'état est juste du texte et la date est une date. Encore dans les premiers stades de l'emballage de ma tête autour de Mongo et se faire une idée de la meilleure façon de faire les choses.MongoDB, renvoie le document récent pour chaque ID utilisateur de la collection

Est-ce que mapreduce serait la meilleure solution ici, la carte émet tous, et réduit conserve un enregistrement de la dernière, ou y at-il une solution intégrée sans sortir mr?

Répondre

0

Il y a un distinct command, mais je ne suis pas sûr que ce soit ce dont vous avez besoin. Distinct est une sorte de commande "query" et avec beaucoup d'utilisateurs, vous allez probablement vouloir enrouler des données pas en temps réel.

Map-Reduce est probablement une façon d'aller ici.

Phase de carte: Votre key serait simplement un ID. Votre value serait quelque chose comme le suivant {current_status:'blah',date:1234}.

Réduire la phase: Étant donné un tableau de valeurs, vous devez saisir le plus récent et le renvoyer uniquement.

Pour que cela fonctionne de manière optimale, vous aurez probablement envie de regarder une nouvelle fonctionnalité de 1.8.0. Le "re-reduce" feature. Vous permettra de traiter uniquement de nouvelles données au lieu de retraiter toute la collection de statuts.

L'autre façon de le faire est de construire une « plus récente » collection et attacher l'état à insérer cette collection. Ainsi, lorsque vous insérez un nouveau statut pour l'utilisateur, vous mettez à jour son "plus récent". En fonction de l'importance de cette fonction, vous pouvez éventuellement faire les deux choses.

+0

Merci, je pense que ces deux approches pourraient valoir la peine d'être examinées, en particulier la re-réduire. – Peck

+0

En pensant à l'approche de collection la plus récente, il semble que cela ajouterait beaucoup de frais généraux au processus d'insertion, quelque chose que j'aimerais éviter puisque cela faisait partie de ma raison d'aller avec mongo de toute façon. Je devrais rechercher/enlever le statut avec l'identification que j'insère pour chaque identification. Bien que cela ne soit pas rapide puisque sa collection est indexée et plus petite, mongo a le "problème" de verrouiller toute la collection pour des suppressions, donc il semble que ce serait un gros compromis à faire. – Peck

+0

Vous pouvez faire un «upsert» qui sera très rapide. Le 'upsert' est *" si existe update else create "*. Il n'y a donc pas de suppression ou de requête supplémentaire. Dans JS, cela ressemble à 'db.most_recent.update ({_ id: id_utilisateur}, {status: "blah"}, false, true), vérifiez votre pilote de langue pour "upsert". –

0

Solution actuelle qui semble fonctionner correctement.

map = function() {emit(this.user.id, this.created_at);} 

//We call new date just in case somethings not being stored as a date and instead just a string, cause my date gathering/inserting function is kind of stupid atm 

reduce = function(key, values) { return new Date(Math.max.apply(Math, values.map(function(x){return new Date(x)})))} 


res = db.statuses.mapReduce(map,reduce); 
0

Une autre façon d'obtenir le même résultat serait d'utiliser la commande group, qui est une sorte de mr-raccourci qui vous permet d'agréger sur une clé ou un ensemble de touches. Dans votre cas, il lirait comme ceci:

db.coll.group({ key : { user_id: true }, 
       reduce : function(obj, prev) { 
          if (new Date(obj.date) < prev.date) { 
          prev.status = obj.status; 
          prev.date = obj.date; 
          } 
         }, 
       initial : { status : "" } 
}) 

Cependant, sauf si vous avez un montant fixe plutôt petit nombre d'utilisateurs, je crois fermement qu'une meilleure solution serait, comme suggéré précédemment, de garder une collection séparée contenant seulement le dernier message d'état pour chaque utilisateur.

+1

Merci pour le groupe de suggestion, mais avec le groupe ne pouvant être utilisé avec sharding, c'est une solution que je vais éviter. – Peck

Questions connexes