我的收藏集messages
包含以下文件
{
"_id" : ObjectId("5164218f359f109fd4000012"),
"receiver_id" : ObjectId("5164211e359f109fd4000004"),
"sender_id" : ObjectId("5162de8a359f10cbf700000c"),
"body" : "Hello Billy!!!",
"readed" : false,
"updated_at" : ISODate("2013-04-09T14:11:27.17Z"),
"created_at" : ISODate("2013-04-09T14:11:27.17Z")
}
我需要查询接收给定用户的最后消息(无论是收到的还是已发送的)(按reciever_id + sender_id字段分组)并按created_at排序。
为了更好地解释这个问题,我在SQL中如何做到这一点的一个例子:
SELECT DISTINCT ON (sender_id+receiver_id) * FROM messages
ORDER by (sender_id+receiver_id), created_at DESC
WHERE sender_id = given_user or receiver_id = given_user
我不明白如何用mondodb来解决这个问题。
答案 0 :(得分:2)
MongoDB 2.2+中的Aggregation Framework提供了最明显的查询翻译。 MongoDB手册包含SQL to Aggregation Framework Mapping Chart作为一般指南,尽管这两种方法存在明显差异。
以下是您可以在mongo
shell中尝试的注释示例:
var given_user = ObjectId("5162de8a359f10cbf700000c");
db.messages.aggregate(
// match: WHERE sender_id = given_user or receiver_id = given_user
// NB: do the match first, because it can take advantage of an available index
{ $match: {
$or:[
{ sender_id: given_user },
{ receiver_id: given_user },
]
}},
{ $group: {
// DISTINCT ON (sender_id+receiver_id)
_id: { sender_id: "$sender_id", receiver_id: "$receiver_id" }
}},
// ORDER by (sender_id+receiver_id), created_at DESC
{ $sort: {
sender_id: 1,
receiver_id: 1,
created_at: -1
}}
)
示例结果:
{
"result" : [
{
"_id" : {
"sender_id" : ObjectId("5162de8a359f10cbf700000c"),
"receiver_id" : ObjectId("5164211e359f109fd4000004")
}
}
],
"ok" : 1
}
您可能希望在分组上添加其他字段,例如收到的消息数。
如果您确实想将sender_id + receiver_id组合到一个字段中,可以使用MongoDB 2.4 +中的$concat
运算符。
答案 1 :(得分:1)
没有明确的方法可以这样做。让我们回顾一下解决方法:
方式1:
在代码级别执行distinct(在查找之后),然后使用find
:
db.message.find({$or:[{sender_id:?}, {receiver_id:?}]})
方式2:使用聚合框架:
db.message.aggregate( [
{$match: {$or:[{sender_id:?}, {receiver_id:?}]},
$group: { _id: {sender:"$sender_id", receiver:"$receiver_id"},
other: { ... } } },
$sort: {sender_id,receiver_id,...}
] )
这种问题出现在排序级别,因为sender_id, receiver_id
与sender_id+receiver_id
方式3:介绍代理字段sender_id + receiver_id,然后根据Stennie提示使用find
甚至distinct
。