【问题标题】:How to find the most recent item in a group using MongoDB aggregation framework?如何使用 MongoDB 聚合框架查找组中的最新项目?
【发布时间】:2015-05-31 17:03:48
【问题描述】:

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

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 包含发送消息的人的 id,receiver 包含将接收它的人的 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));
});

这个查询给出了与某个人交谈过的所有人,但它的顺序不正确,如果我更改排序顺序,它会给我准确的结果。

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

【问题讨论】:

  • 我不明白你为什么需要 $group 参数。您的 $match 和 $sort 工作正常。
  • @ThomasBormans 因为我只需要拥有一次 id,所以我认为按 2 个字段分组会产生不同的 id。我试图删除 $group 参数,它给了我一些我什至没有在集合中的 id。
  • “它给了我一些我什至没有收藏的 id” $match$sort 无法“生成”新的 id - - 也不会产生重复的 ID。 $match 将一个输入文档映射到零或一个输出文档。 $sort 将一个输入文档映射到一个输出文档。无论如何,他们都没有改变文档。
  • @AndraNico 也许你应该用更详细的解释和想要的回应来更新你的问题。
  • @ThomasBormans 我更新了我的问题,希望我现在解释得更好。

标签: mongodb mongodb-query


【解决方案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") }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-08
    • 2019-02-01
    • 2013-03-02
    • 2023-01-31
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    相关资源
    最近更新 更多