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
相关产品推荐
相关产品推荐

