如何使用MongoDB聚合框架查找组中的最新项?

时间:2015-05-30 16:25:03

标签: mongodb mongodb-query

我有一个存储邮件的集合,它看起来像这样:

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

发件人包含发送邮件的人的ID,收件人包含将收到该邮件的人的ID。

我想创建一个最近的联系人列表。也就是说,找到某个人所说的所有人(作为发送者或接收者),按日期排序降序。如果有重复,我只需保留最近的联系方式。

例如:如果我搜索与id = 1的人交谈的人,我想获得以下人员ID:4,2,3(与他交谈的人):4是最新的人(日期30-May-15 3:30:05 PM),2日前4日(日期30-May-15 3:21:48 PM),3日前2日(日期30-May-15 3:20:00 PM) )。

我尝试了这个查询:

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));
});

此查询向我提供了某个人所说过的所有人,但它的顺序不正确,如果我更改了排序顺序,它会给我确切的结果。

如何按日期对收藏品进行排序?

1 个答案:

答案 0 :(得分:1)

鉴于该数据集:

{ "_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") }

显然您只想保留最近的联系人,您可以使用以下方法获得所需的结果:

> 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}},
])
  • $match阶段是一个简单的过滤器;
  • $project阶段会将对话者推断为发送者或接收者;
  • $group阶段会为每个对话者分组多个结果,并在每个组中保留最近的通话($max)日期;
  • 最后,$sort阶段将结果文档从最新到最近的顺序排序。

运行该管道,它将返回:

{ "_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") }