我使用 mongo 存储用户的消息。
这是我的收藏模型。
_id // mongo id of the message
subject // subject of the message
msg // message
recipients // array of users id
sender // user id
inReplyTo // id of the message that i'm replying
references // array of all the ids of the conversation
sended // date of dispatch
我想列出每页收到30条消息的列表。如果有对话,在列表中,我只希望看到对话的最后一条消息。
我使用猫鼬和 nodejs 。
这些是一次对话的2条消息。
[
// the first message of the conversation
{
"_id" : ObjectId("5b9a7218b83256001799a114"),
"inReplyTo" : null,
"references" : [ ],
"recipients" : [ 1, 2, 3 ],
"subject" : "Subject of the first message",
"msg" : "Text of the first message",
"sender" : 4,
"sended" : ISODate("2018-09-13T16:20:08.997+02:00"),
},
// the reply to the first message
{
"_id" : ObjectId("5b9bc0d67d6acc001732a58a"),
"inReplyTo" : ObjectId("5b9a7218b83256001799a114"),
"references" : [
ObjectId("5b9a7218b83256001799a114")
],
"recipients" : [ 4 ],
"subject" : "FDW: Subject of the first message",
"msg" : "Text of the reply",
"sender" : 1,
"sended" : ISODate("2018-09-14T16:08:22.934+02:00"),
}
]
如何使用聚合?
还是我必须在查询后过滤它们?又如何?
答案 0 :(得分:0)
更新1:我更新了我的答案代码以适合您发布的示例数据。该消息将搜索出发送给用户或由用户发送的每条消息,并按会话将其分组,并仅返回每条消息的第一(最后)。
Message.aggregate([
// Get the first message of each conversation concerning user
{
$match: {
$and: [
{
$or: [
{ recepient: USER_ID }, // User is in recepients
{ sender: USER_ID } // or the sender
],
},
]
}
},
// Add a conversation field to group them by conversation
{
$addFields: {
conversation: {
$cond: {
if: {
$references: { $exists: false }
},
then: '$_id',
else: { $arrayElemAt: ['$references', 0]}
}
}
}
},
// Sort messages by 'sended' field (descending, most-recent first)
{
$sort: {
sended: -1
}
},
// Group by conversation, collect only the most recent (first) message of each conversation
// { _id: conversation-id#1, message: { ...}}, { _id: conversation-id#2, message: { ...}}, ...
{
$group: {
_id: '$conversation',
message: { $first: '$$ROOT' }
}
}
], function(err, recentMessages) {
if(err) { /** Handle error.. */ }
});
答案 1 :(得分:0)
这是您要执行的操作:
db.collection.aggregate({
$match: {
"recipients": userId // keep only documents where my userId is in the list of recipients
}
}, {
$sort: {
"sended": -1 // sort by "most recent first" - kindly note that it should be "sent" not "sended"
}
}, {
$limit: 1 // return no more than one document
})