J'ai une collection de messsages avec les champs suivants: _id
, senderId
, receiverId
, dateSubmittedMs
, message
, et pour un utilisateur donné je veux lui retourner le dernier message de tous les autres utilisateurs. Ainsi, par exemple, s'il y a des utilisateurs Alex, Barb, Chuck, Dora, je voudrais retourner le message le plus récent entre Alex et chacun de Barb, Chuck et Dora. Quelle est la meilleure façon de procéder? Puis-je le faire en une seule étape en utilisant l'agrégation? Les exemples d'agrégation dans la documentation en ligne officielle (http://docs.mongodb.org/manual/reference/aggregation/min/) montrent comment trouver l'âge le plus bas au sein d'une collection, mais ce dont j'ai besoin est quelque chose d'analogue à trouver le nom de la personne la plus jeune sur des groupes de personnes.
Voici mon approche actuelle:
Étape 1: Trouvez la valeur la plus élevée pour dateSubmitted
sur tous les messages envoyés et reçus par Alex, le regroupement sur les autres utilisateurs:
var M = Messages.aggregate(
{$match:
{$or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]}
},
{$group: {_id: "$receiverId", lastestSubmitted: {$max: "$submitted"} }}).fetch();
Étape 2: Créer un tableau de ces valeurs les plus élevées de DateSubmitted:
var MIds = _.pluck(M,'lastestSubmitted');
Etape 3: Trouver ces messages, par senderID, ReceiverID et latestSubmitted:
return Messages.find(
{submitted: {$in: MIds}, $or: [{senderId: 'Alex'}, {receiverId: 'Alex'}]},
{$sort: {submitted: 1}}
});
Il y a deux problèmes avec ceci:
- Peut-il être fait en une seule étape au lieu de trois? Peut-être à travers une commande mapReduce ou Aggregate?
- Au lieu de grouper uniquement sur le
receiverId: 'Alex'
, est-il possible de regrouper quelque chose comme:$or [{receiverId: 'Alex', senderId: 'Barb'}, {senderId: 'Alex', receiverId: 'Barb'}]
? (mais pour CHACUN des autres utilisateurs) Cela me permettrait d'obtenir le dernier message dans une conversation entre deux participants avec lesquels Alex a conversé. Ainsi, par exemple:
Des suggestions?
Merci pour votre aide. J'ai essayé de l'implémenter, et cela fonctionnerait probablement si Meteor prenait en charge l'agrégation côté client, mais comme je viens de le découvrir (http://stackoverflow.com/questions/11266977/are-group-by-aggregation-queries-possible- in-météore-encore), météore ne l'est pas encore. Il y a un travail autour (https://github.com/meteor/meteor/pull/644), mais ce n'est pas réactif. Je vais essayer ça dans le shell mongodb et voir si je peux le faire fonctionner là-bas, juste pour être sûr. –
J'ai essayé dans shell et copié collé le code que j'ai développé là à votre exemple. Honnêtement, je n'ai pas essayé dans Meteor pendant que je supposais que votre code dans la question fonctionne. Je suis curieux de vos tests, donc ce serait génial si vous pouviez fournir les résultats. Et j'espère que ça a aidé. – attish
Bonjour @attish, merci pour le suivi. J'ai essayé d'implémenter vos deux solutions dans le shell mongodb, mais ils ne renvoient qu'un résultat global, alors qu'ils devraient retourner un résultat par conversation (si Alex avait des conversations avec Barb et Chuck, alors deux résultats devraient être retournés: le dernier message avec Barb et le dernier message avec Chuck). Avez-vous pu obtenir plus d'un résultat global? –