如何使用 MongoDB 聚合框架查找组中的最新项目?
How to find the most recent item in a group using MongoDB aggregation framework?
我有一个 collection 存储消息的地方,它看起来像这样:
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是最新的人(日期 2015 年 5 月 30 日 3:30:05 下午),2 人在 4 点之前(日期 2015 年 5 月 30 日 3:21:48 下午),3 人在 2 点之前(日期 2015 年 5 月 30 日 3:20:00下午)。
我试过这个查询:
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));
});
此查询为我提供了与某个人交谈过的所有人员,但它的顺序不正确,如果我更改排序顺序,它会为我提供准确的结果。
如何按日期对 collection 进行排序?
鉴于该数据集:
{ "_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
stage will group multiple results per interlocutor, keeping the most recent call ($max
)日期;
- 最后
$sort
阶段将生成的文档从最新到最旧排序。
运行那个管道,它会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") }
我有一个 collection 存储消息的地方,它看起来像这样:
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是最新的人(日期 2015 年 5 月 30 日 3:30:05 下午),2 人在 4 点之前(日期 2015 年 5 月 30 日 3:21:48 下午),3 人在 2 点之前(日期 2015 年 5 月 30 日 3:20:00下午)。
我试过这个查询:
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));
});
此查询为我提供了与某个人交谈过的所有人员,但它的顺序不正确,如果我更改排序顺序,它会为我提供准确的结果。
如何按日期对 collection 进行排序?
鉴于该数据集:
{ "_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
stage will group multiple results per interlocutor, keeping the most recent call ($max
)日期; - 最后
$sort
阶段将生成的文档从最新到最旧排序。
运行那个管道,它会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") }