我有一个Chat 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阶段将变得很慢.有没有更好的方法来做到这一点,或者我是不是过早地试图优化一些运行良好的东西?

是的,如果您的数据库中有许多聊天,并且每个聊天的消息数量相对较少,则有一种更好、更高效的方法来实现这一点.

您可以使用$lookup阶段加入消息收集并直接查找最新消息,而不是使用$group阶段来查找每次聊天中的最新消息:

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;
});

我希望它能帮助你.

附注: 你应该 Select 最适合你的方法.

例如,如果您有许多聊天,但消息数量相对较少,那么我提供的方法可能会对您更有效.

然而,如果你的聊天次数少,消息多,那么你的方法就足够了.

Database相关问答推荐

位置运算符($)工作不正确

避免数据库联接的两个查询替换

从仅连接器电源查询制作图表

在哪里存储 PHP 应用程序的数据库登录凭据

java嵌入式库磁盘键值数据库

从 DbDataReader 读取数据的最快方法是什么?

在一次 SQL 查询中更新多行的多列

错误:mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication

JOOQ 与Hibernate

为数据库应用程序留下审计跟踪/更改历史的有效策略?

MySQL 数据库中列名中的连字符

MySQL是否允许使用点创建数据库?

Django:将博客条目查看次数加一,这有效率吗?

如何在 Windows 中将用户添加到 PostgreSQL?

在将字符串插入数据库期间单引号转义

对于 N:M 关系,在 MongoDB 中推荐的级联删除等效项是什么?

从数据库中获取事件

python3k中的sqlite3中的cursor.rowcount总是-1

什么是 ACID 的真实示例?

为什么 Rails 迁移在应用程序中定义外键而不在数据库中定义外键?