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
$matchstage simple filter; - the
$projectstage infer interlocutor sender or receiver; - the
$groupstage group multiple results per interlocutor, keeping recent call ($max) date in each group; - finally
$sortstage 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
Post a Comment