Mongodb 按两个交换字段分组的查询
我收集了Mongodb 按两个交换字段分组的查询,mongodb,mongoid,Mongodb,Mongoid,我收集了信息和以下文档 { "_id" : ObjectId("5164218f359f109fd4000012"), "receiver_id" : ObjectId("5164211e359f109fd4000004"), "sender_id" : ObjectId("5162de8a359f10cbf700000c"), "body" : "Hello Billy!!!", "readed" : false, "updated_at" : ISODate("201
信息
和以下文档
{
"_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")
}
我需要为给定用户(按接收者id+发送者id字段分组)查询receive last messages(无论是Received还是Send),并按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解决这个问题。没有明确的方法。让我们回顾一下解决方法: 方式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\u id,receiver\u id
与sender\u id+receiver\u id
方法3:引入代理字段发送者id+接收者id,然后根据Stennie提示使用
find
甚至distinct
。没有明确的方法。让我们回顾一下解决方法:
方式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\u id,receiver\u id
与sender\u id+receiver\u id
方法3:引入代理字段sender\u id+receiver\u id,然后根据Stennie提示使用find
甚至distinct
。在MongoDB 2.2+中提供了最明显的查询翻译。MongoDB手册包括一个通用指南,尽管这两种方法有明确的区别
下面是一个注释示例,您可以在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
}
您可能希望在分组中添加其他字段,例如接收的邮件数
如果您确实想将发送者id+接收者id组合到一个字段中,您可以使用MongoDB 2.4+中的运算符。MongoDB 2.2+中的运算符提供了最明显的查询翻译。MongoDB手册包括一个通用指南,尽管这两种方法有明确的区别
下面是一个注释示例,您可以在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
}
您可能希望在分组中添加其他字段,例如接收的邮件数
如果您确实想将发送者id+接收者id组合到一个字段中,您可以使用MongoDB 2.4+中的运算符。与您的方式#3和代理字段一起使用,您实际上可以在该字段上使用命令,而不是使用
find()
.way#2和$group:{id:{sender:$sender#id],receiver:$receiver#id}
似乎不起作用,因为当交换字段时,其结果是make new entity。@ole-您不需要交换字段,因此即使sender为null,那么键也将是相同的{null,ObjectId(“5164211e359f109fd4000004”)}
通过您的方式#3和代理字段,您实际上可以在该字段上使用命令,而不是find()
.Way#2 with$group:{sender:$sender:$sender\u id,receiver:$receiver\u id”}
似乎不起作用,因为在交换字段时,其结果是生成新实体。@ole-您不需要交换字段,所以即使sender为null,键也将是相同的{null,ObjectId(“5164211e359f109fd4000004”)}
在给定的情况下,用户不仅要发送,还要接收一些消息。组无法按需要工作,因为给定用户的字段(发送者id、接收者id)已交换,并且结果中出现了新实体。因此,我在SQL中使用了发送者id+接收者id
。如果您将给定用户匹配为发送者id
或接收者id
,这将涵盖该用户发送或接收消息的情况,应该与您的SQL查询等效。分组输出将区分相同两个用户交换电子邮件的情况:{sender\u id:user1,receiver\u id:user2}
vs`{sender\u id:user2,receiver\u id:user1}。如果您确实想要唯一对,那么您的SQL查询也需要更改。我的SQL示例工作正常,因为在SQL中id是整数。无论如何,感谢您提供了一个帮助我理解一些事情的好解决方案。顺便问一下,如果我将结构更改为嵌入式用户:{sender_id:“5162de8a359f10cbf70000c”,receiver_id:“5162de8a359f10cbf7000004”}
,您认为如何。这对我有帮助吗?在…中为用户指定了带有复选框的mb,例如。在指定的情况下,用户不仅发送消息,还接收一些消息。组无法按需要工作,因为给定用户的字段(发送者id、接收者id)已交换,并且结果中出现了新实体。因此,我在SQL中使用了发送者id+接收者id
。如果您将给定用户匹配为发送者id
或接收者id
,这将涵盖该用户发送或接收消息的情况,应该与您的SQL查询等效。分组输出将区分相同两个用户交换电子邮件的情况:{sender\u id:user1,receiver\u id:user2}
vs`{sender\u id:user2,receiver\u id:user1}。如果您确实想要唯一对,那么您的SQL查询也需要更改。我的SQL示例工作正常,因为在SQL中id是整数。无论如何,感谢您提供了一个帮助我理解一些事情的好解决方案。顺便问一下,如果我将结构更改为嵌入式用户:{sender_id:“5162de8a359f10cbf70000c”,receiver_id:“5162de8a359f10cbf7000004”}
,您认为如何。这对我有帮助吗?在…
中为用户提供了带有类似于的复选框的mb。