我有2个架构:
var UserSchema = new Schema({
login: {type:String, unique: true, trim:true, index:true},
password: String
)};
var MessageSchema = new Schema({
text: String,
from_id: {type:mongoose.Schema.ObjectId, ref: 'user', index:true},
to_id: {type:mongoose.Schema.ObjectId, ref: 'user', index:true},
date: Number
});
现在举例来说,我在数据库中有4个用户。假设user1向每个其他用户发送了5条消息,user2和user3均回复了user1消息。现在我需要从每个对话框中只返回一条最近的消息。我怎么能这样做?
答案 0 :(得分:1)
这样做的一个好方法是使用MongoDB的聚合框架。
我不是100%明确你的具体用例,但我认为使用$unwind
将所有消息放在同一个地方,然后过滤{{1} }}如果您希望它仅显示最新的消息,则为$setUnion
和$sort
。
这是指向快速参考的链接:http://docs.mongodb.org/manual/meta/aggregation-quick-reference/
希望这有帮助,祝你好运!
答案 1 :(得分:1)
这里所做的一切都是mongo控制台,你必须自己翻译给你的司机
如果您要查询特定会话,请在邮件中添加conversation_id
(可能是用户名组合或只是随机字符串),然后您可以与
db.messages.aggregate({$sort:{date:-1}},
{$group:{_id:"$conversation_id", message:{$first:"$$ROOT"}})
或者只是将消息嵌入像David K这样的对话文档中。似乎已经认为你已经在做了什么。
我构建了一个可以满足您需求的聚合,但是在看到这个之后你可能想要用简单的方法(可能有人会想到更短的一个)。
首先在您的架构之后建模集合:
> db.chat.find().pretty()
{ "from" : 1,
"to" : 2,
"text" : "First from 1 to 2",
"date" : 1}
{ "from" : 2,
"to" : 1,
"text" : "First answer from 2 to 1",
"date" : 2}
{ "from" : 1,
"to" : 2,
"text" : "Second from 1 to 2",
"date" : 3}
{ "from" : 1,
"to" : 3,
"text" : "First 1 to 3",
"date" : 3}
{ "from" : 3,
"to" : 1,
"text" : "Reply 3 to 1",
"date" : 4}
_id
规定了可读性,当您看到两个对话时,用户1
和2
之间以及1
和3
之间的对话。
现在是聚合查询:
db.chat.aggregate({$project: {to:1,from:1,date:1,text:1,duplicator:{$const: [0,1]}}},
{$unwind:"$duplicator"},
{$group:{_id:"$_id",
parts:{$push:{$cond:[{$eq:"$duplicator",0]},"$from","$to"]}},
messages:{$addToSet: {text:"$text",date:"$date"}}}},
{$unwind:"$parts"},
{$sort:{parts:1}},
{$group:{_id:"$_id",
parts:{$push:"$parts"},
messages:{$first:"$messages"}}},
{$sort:{"messages.date":-1}},
{$group:{_id:"$parts", last_message:{$first:"$messages"}}})
输出:
{ "_id" : [1,2],
"last_message" : [{ "text" : "Second from 1 to 2",
"date" : 3 }]
}
{ "_id" : [1,3],
"last_message" : [{"text" : "Reply 3 to 1",
"date" : 4}]
}
最后两部分($sort
和$group
)与简单方法相同。其余的是为参与者构建一个名为conversation_id
的{{1}}。这是由
parts
duplicator
中推送to
和from
。 parts
将使用conversation_id 上述步骤受到启发by this answer
parts
parts
他们因为$sort
[1,2] != [2,1]
他们再次成为一个数组Tose步骤会产生一个会话ID,然后可以像上面两行aggreate中提出的那样使用它。
根据你想要查询它的方式构建你的模式,因为用奇怪的聚合强奸mongodb只是有趣,直到它在自卫中踢你的球......
如果您只想要特定会话的最后一条消息,可以使用
$group