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

MongoDB(Mongoose)查询:如何提取两字段的唯一用户ObjectID?

解决MongoDB聚合提取唯一对话用户ID的问题

你的问题出在$setUnion的使用方式上:$from是单个ObjectId值,而$to是数组,$setUnion要求两个输入都是数组类型,所以直接用$setUnion: ["$from", "$to"]没法正确合并去重。下面是修正后的聚合查询方案:

完整聚合代码

const currentUserId = new mongoose.Types.ObjectId(req.user.id);

const uniqueUsers = await Message.aggregate([
    // 匹配当前用户参与的所有消息
    {
        $match: {
            $or: [
                { from: currentUserId },
                { to: { $in: [currentUserId] } }
            ]
        }
    },
    // 将单个from字段转为数组,和to数组合并成所有参与者数组
    {
        $addFields: {
            allParticipants: { $concatArrays: [[ "$from" ], "$to"] }
        }
    },
    // 拆分参与者数组,每条文档对应一个用户ID
    { $unwind: "$allParticipants" },
    // 全局去重收集所有唯一用户ID
    {
        $group: {
            _id: null,
            uniqueUserIds: { $addToSet: "$allParticipants" }
        }
    },
    // 移除当前用户自己的ID,得到最终对话列表
    {
        $project: {
            _id: 0,
            uniqueConversations: {
                $setDifference: [ "$uniqueUserIds", [ currentUserId ] ]
            }
        }
    }
]);

// 结果会在uniqueUsers[0].uniqueConversations中
console.log(uniqueUsers[0].uniqueConversations);

代码解释

  1. $addFields阶段:用$concatArrays把单个的from包装成数组,再和to数组合并,得到包含这条消息所有参与者的数组allParticipants。
  2. $unwind阶段:将数组拆分成多条单元素文档,为后续全局去重做准备。
  3. $group阶段:用$addToSet收集所有用户ID,自动实现全局去重。
  4. $project阶段:用$setDifference从唯一ID数组中移除当前用户自己的ID,直接得到需要的对话用户列表。

用你的示例数据测试,最终会得到:

["671175392a0bcfdb66f83401", "6708368712a817cd73810b5e"]

完全符合你后续移除当前用户ID的需求。

内容的提问来源于stack exchange,提问作者bchow2001

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 00:45:11