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

MongoDB聚合Lookup:多条件匹配及当前用户_id获取方法

解决MongoDB Lookup多条件关联匹配问题

需求说明

需要在User集合的聚合Lookup操作中,关联Chats集合,匹配Chat文档的from或to字段,使其分别对应当前用户的_id(作为发送方或接收方),并为用户文档添加chatHistory字段存储关联的聊天记录。

示例集合数据

User集合

[{
    _id: { $oid: "64428badffd445ba3c11a9b4" },
    firstName: "test",
    lastName: "user",
    type: { $numberInt: "2" },
    email: "test@user.com",
    password: "$2a$10$gm25OtxxAGl3Cj4V.ZoQ0OngID0eAfaAdQh5sQeKJ0aTyoVukChkG",
    createdAt: { $date: { $numberLong: "1682082733141" } },
    updatedAt: { $date: { $numberLong: "1682082733141" } },
    __v: { $numberInt: "0" },
}]

Chats集合

[{
    _id: { $oid: "644f892004492f9c01296861" },
    from: { $oid: "64428badffd445ba3c11a9b4" },
    to: { $oid: "644a07431babb4a2df531f2a" },
    message: "hello",
    createdAt: { $date: { $numberLong: "1682934048968" } },
    updatedAt: { $date: { $numberLong: "1682934048968" } },
    __v: { $numberInt: "0" },
}]

错误代码示例

用户尝试的两种错误实现:

初始代码

const recentChats = await User.aggregate([
    {
      $lookup: {
        from: "chats",
        as: "chatHistory",
        pipeline: [
          {
            $match: {
              $or: [{ from: req.params.id }, { to: "$$id" }],
            },
          },
        ],
      },
    },
]);

尝试修改后的错误代码

const recentChats = await User.aggregate([
    {
      $lookup: {
        from: "chats",
        as: "chatHistory",
        let: {
          vars: { id: { $getField: "_id" } },
        },
        pipeline: [
          {
            $match: {
              $or: [{ from: req.params.id }, { to: "$$id" }],
            },
          },
        ],
      },
    },
]);

正确实现方式

代码实现

// 先将req.params.id转换为ObjectId,确保类型匹配
const userId = mongoose.Types.ObjectId(req.params.id);

const recentChats = await User.aggregate([
    {
      $lookup: {
        from: "chats",
        as: "chatHistory",
        // 正确定义lookup内部变量,直接引用当前User文档的_id
        let: { userId: "$_id" },
        pipeline: [
          {
            $match: {
              // 使用$expr来引用lookup传递的变量,同时匹配两个条件
              $expr: {
                $or: [
                  { $eq: ["$from", userId] },
                  { $eq: ["$to", "$$userId"] }
                ]
              }
            }
          }
        ],
      },
    },
]);

关键修正点

  1. 变量定义错误:之前的let里嵌套vars是错误语法,let需要直接声明键值对形式的变量,这里用userId: "$_id"直接引用当前User文档的_id。
  2. 类型匹配问题:req.params.id是字符串类型,而MongoDB文档的_id是ObjectId类型,需要先转换为ObjectId避免匹配失败。
  3. 条件匹配语法:在子管道的$match中,引用let定义的变量需要使用$expr包裹,否则无法识别$$userId这类变量引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:05:39