How to find the most recent item in a group using MongoDB aggregation framework? -


i have collection store messages , looks this:

id sender receiver date ------------------------ 1     1       2    30-may-15 3:14:48 pm 2     2       1    30-may-15 3:16:28 pm 3     1       3    30-may-15 3:20:00 pm 4     1       2    30-may-15 3:21:48 pm 5     3       2    30-may-15 3:25:15 pm 6     4       1    30-may-15 3:30:05 pm 

sender contains id of person sent message , receiver contains id of person receive it.

i want create list of recent contacts. is, find people person has spoken (as sender or receiver), ordered descending date. in case of duplicates, need keep recent contact.

for example: if search persons spoke person id=1 want obtain following person ids: 4, 2, 3(the persons whom had spoken): 4 latest person (date 30-may-15 3:30:05 pm), 2 before 4 (date 30-may-15 3:21:48 pm), , 3 before 2(date 30-may-15 3:20:00 pm).

i tried query:

messages.aggregate({$match: {$or:[{sender: searched_id}, {receiver: searched_id}]}},                  {$sort: {date: -1}},                  {$group: {"_id": {sender: "$sender", receiver: "$receiver"}}},                   function(err, docs){     console.log(json.stringify(docs)); }); 

this query gives me people person have spoken, it's not in correct order , if change sorting order, gives me exact result.

what can sort collection date?

given dataset:

{ "_id" : 1, "sender" : 1, "receiver" : 2, "date" : isodate("2015-05-30t15:14:48z") } { "_id" : 2, "sender" : 2, "receiver" : 1, "date" : isodate("2015-05-30t15:16:28z") } { "_id" : 3, "sender" : 1, "receiver" : 3, "date" : isodate("2015-05-30t15:20:00z") } { "_id" : 4, "sender" : 1, "receiver" : 2, "date" : isodate("2015-05-30t15:21:48z") } { "_id" : 5, "sender" : 3, "receiver" : 2, "date" : isodate("2015-05-30t15:25:15z") } { "_id" : 6, "sender" : 4, "receiver" : 1, "date" : isodate("2015-05-30t15:30:05z") } 

as apparently want keep most recent contact, can achieve desired result using:

> searched_id = 1 > db.test.aggregate([  {$match: {$or: [{sender: searched_id}, {receiver: searched_id}]}},  {$project: { _id: 1, date: 1,               interlocutor: {$cond: [{$eq: ["$sender", searched_id]},"$receiver","$sender"]}}},  {$group: {_id: "$interlocutor", date: {$max: "$date"}}},  {$sort: {date: -1}}, ]) 
  • the $match stage simple filter;
  • the $project stage infer interlocutor sender or receiver;
  • the $group stage group multiple results per interlocutor, keeping recent call ($max) date in each group;
  • finally $sort stage orders resulting documents least recent.

running pipeline, return:

{ "_id" : 4, "date" : isodate("2015-05-30t15:30:05z") } { "_id" : 2, "date" : isodate("2015-05-30t15:21:48z") } { "_id" : 3, "date" : isodate("2015-05-30t15:20:00z") } 

Comments

Popular posts from this blog

node.js - Using Node without global install -

How to access a php class file from PHPFox framework into javascript code written in simple HTML file? -

java - Null response to php query in android, even though php works properly -