我有一个聊天 MongoDB 数据库,其中包含以下集合:
chats: {
chat_id: string, // indexed 1, unique
last_updated: number, // indexed -1
// other data...
}
messages: {
chat_id: string; // indexed 1
message_id: string; // indexed 1, unique
timestamp: number; // indexed -1
// other data...
}
我希望能够查询 10 个最近的聊天并接收聊天文档以及与该聊天相关的最新消息。目前,我正在做的是:
// step 1: find the 10 most recent chats
const chats = await db.collection('chats')
.find()
.sort({last_updated: -1})
.limit(10)
.toArray();
// step 2: use $group to find the most recent message in each chat
const messages = await db.collection('messages').aggregate([
{ $match: { chat_id: { $in: chats.map(chat => chat.chat_id) } } },
{ $sort: { timestamp: -1 } },
{ $group: { _id: '$chat_id', latest_message: { $first: '$$ROOT' } } }
]).toArray();
我担心如果聊天有很多与之相关的消息,$sort 和 $group 阶段会很慢。有没有更好的方法来做到这一点,或者我是否过早地尝试优化一些可以正常工作的东西?
我认为您当前的方法是正确的,并且应该可以正常工作,即使您的聊天会有很多与之相关的消息。
我担心如果聊天有很多与之相关的消息,$sort 和 $group 阶段会很慢。有没有更好的方法来做到这一点,或者我是否过早地尝试优化一些可以正常工作的东西?
是的,如果您的数据库中有很多聊天记录并且每个聊天记录的消息数量相对较少,那么有一种更好更有效的方法来执行此操作。
您可以使用
$group
阶段加入消息集合并直接查找最新消息,而不是使用 $lookup
阶段查找每个聊天中的最新消息:
const chats = await db.collection('chats')
.find()
.sort({last_updated: -1})
.limit(10)
.toArray();
const messages = await db.collection('messages')
.aggregate([
{
$lookup: {
from: 'chats',
localField: 'chat_id',
foreignField: 'chat_id',
as: 'chat'
}
},
{ $unwind: '$chat' },
{ $sort: { 'chat.last_updated': -1 } },
{ $limit: 1 }
])
.toArray();
const joinedChats = chats.map((chat, index) => {
chat.latest_message = messages[index];
return chat;
});
希望能帮到你。
P.s. 您应该选择最适合您的方法。
例如,如果您有很多聊天且消息数量相对较少,那么我提供的方法可能对您来说更有效。
但是,如果您的聊天量较少且消息较多,那么您的方法就更足够了。