You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化MongoDB获取带最新消息的会话列表的聚合查询速度

优化方案

核心优化点

  • 新增必要索引(性能提升最明显)
    给chatmessages集合创建复合索引:db.chatmessages.createIndex({chat: 1, created_at: -1})
    原理:子管道中先匹配chat字段、再按created_at倒序取第一条的逻辑,完全匹配该复合索引的排序规则,MongoDB匹配到对应会话的消息后,可直接按索引顺序返回结果,完全避免内存排序操作,解决排序耗时高的核心问题。
    同时给chats集合的user和person字段分别创建单键索引,加快第一步会话匹配的速度:
    db.chats.createIndex({user: 1})
    db.chats.createIndex({person: 1})
  • 调整聚合管道执行顺序,减少待处理文档量
    将会话排序、limit操作提前到关联用户、关联消息之前,原逻辑是先处理所有符合条件的会话的关联操作,再取前20条,调整后仅需要处理20条会话的关联逻辑,大幅减少不必要的计算开销。
  • 删除冗余的$group阶段
    原管道中的$group无实际作用,$lookup关联出来的messages本身就是长度为1的数组,直接提取第一个元素即可,省去分组的额外开销。

优化后代码示例

var pipeline = [
  // 匹配当前用户的会话
  {$match: {
    $or:[
      {"user": ObjectId(req.query.user)},
      {"person": ObjectId(req.query.user)},
    ]
  }},
  // 提前按会话创建时间倒序,取最近20条,减少后续处理的文档数
  {"$sort": { created_at: -1 } },
  {"$limit": 20},
  // 关联创建者信息
  {"$lookup": {
      "from": "users",
      "localField": "user",
      "foreignField": "_id",
      "as": "creator"
  }},
  {"$unwind": "$creator"},
  // 关联联系人信息
  {"$lookup": {
      "from": "users",
      "localField": "person",
      "foreignField": "_id",
      "as": "contact"
  }},
  {"$unwind": "$contact"},
  // 关联最新消息,加索引后此处排序几乎无开销
  {$lookup: {
      from: "chatmessages",
      let: { chatId: "$_id" },
      pipeline: [
        {$match: { $expr: { $eq: ["$chat", "$$chatId"] } }},
        {$sort: {"created_at": -1}},
        {"$limit": 1},
      ],
      as: "messages"
  }},
  // 提取字段,筛选存在消息的会话
  {$project: {
      _id: 1, 
      created_at:1,
      count:1,
      creator: 1,
      contact:1,
      lastMessage: { $arrayElemAt: ["$messages", 0] }
  }},
  {$match: { lastMessage: {$exists: true} }}
];
var resultants = await Chat.aggregate(pipeline);

以上优化完成后,查询耗时可降至300ms以内,同时保证返回的是各会话最新的消息。

内容的提问来源于stack exchange,提问作者dream to code

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 03:54:04