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

Node.js+Mongoose消息应用:去重获取历史对话用户列表

解决Mongoose获取对话用户列表(去重+排除自身)的问题

针对你遇到的查询结果包含自身、用户名称重复的问题,这里提供两种实用的解决方式:

方法一:使用MongoDB聚合管道(推荐)

直接在数据库层面完成筛选、转换、去重和排除操作,性能更优,适合数据量较大的场景:

const currentUser = req.user.username;

const conversationPartners = await Message.aggregate([
  // 筛选所有包含当前用户的消息记录
  {
    $match: {
      $or: [
        { sender: currentUser },
        { receiver: currentUser } // 注意:如果你的数据库字段是reciever(拼写错误),请保持一致
      ]
    }
  },
  // 生成对话伙伴字段:判断当前用户是发送方还是接收方,取对应的另一方
  {
    $addFields: {
      conversationPartner: {
        $cond: {
          if: { $eq: ["$sender", currentUser] },
          then: "$receiver",
          else: "$sender"
        }
      }
    }
  },
  // 按对话伙伴分组,自动去重
  {
    $group: {
      _id: "$conversationPartner",
      lastMessageTime: { $max: "$createdAt" } // 可选:保留最后一条消息的时间,用于后续排序
    }
  },
  // 排除当前用户自身
  {
    $match: { _id: { $ne: currentUser } }
  },
  // 整理输出格式
  {
    $project: {
      _id: 0,
      username: "$_id",
      lastMessageTime: 1
    }
  }
]);

方法二:查询后在代码层处理

如果消息数据量较小,也可以先查询所有匹配的消息,再在Node.js中处理去重和排除:

const currentUser = req.user.username;
const messages = await Message.find({
  $or: [
    { sender: currentUser },
    { receiver: currentUser }
  ]
});

// 提取所有对话伙伴,去重并排除自身
const conversationPartners = [...new Set(
  messages.map(msg => 
    msg.sender === currentUser ? msg.receiver : msg.sender
  ).filter(partner => partner !== currentUser)
)];

注意事项

  • 检查字段拼写:你代码里写的reciever是拼写错误,正确应为receiver,如果数据库中字段确实是reciever,请保持代码与数据库一致,否则会导致查询失败。
  • 聚合管道的优势:当消息数量较多时,聚合管道避免了将大量数据加载到内存中处理,性能远优于代码层处理。

内容的提问来源于stack exchange,提问作者Halil Emin Çalışkan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:45:36