Mongodb $lookup 聚合 returns 来自外部索引的所有文档

Mongodb $lookup aggregation returns all documents from foreign index

我有一个用户索引

[{
 username: "foo@bar,
 roleIds: [ Types.ObjectId("1234") ]
},
{
 username: "foo@moo,
}]

有了roles

{
    "_id" : ObjectId("60465768f768621ec5828b68"),
    "name" : "admin",
    "permissionIds" : ObjectId("604657e8e715ss1f2d78b945")
}

permissions

{
    "_id" : ObjectId("604657e8e715ss1f2d78b945"),
    "name" : "view-user",
}

当我通过用户名获取用户时,我想补充角色信息。 并非所有用户都有 roleIds 所以我需要能够 return 用户,无论他们是否有 roleIds。

目前对角色的查找总是 returns roles 索引中的每个项目!

我的想法是,我通过数组 roleIds_ids

查找索引 roles 上的 roles 连接

然后我在该查找中使用管道从角色中获取权限信息。

db.getCollection('users').aggregate([
        {
          $match: {
            'username':'foo@bar',
          }
      },
        {
          $lookup: {
            from: 'roles',
            let: {'roleIds': '_id'},
            as: 'roles',
            pipeline: [{
                $lookup: {
                  from: 'permissions',
                  let: {'permissionIds': "_id"},
                  as: 'permissions',
                  pipeline: [
                    {
                      $project: {
                        name: 1
                      }
                    }
                  ]
                }
              },{
                $project: {
                  name: 1,
                  permissions: 1
                }
              }
            ]
          }
        }
      ])

这条路线似乎 return 所有 索引中的 roles 文档,而不管它是否实际上是一个连接。

我是不是马上做错了什么??

您的查询中存在以下错误:

  1. 在两次查找中,您都将错误的变量传递给 let 内的 pipeline
  2. 管道内缺少执行实际连接操作的 $match 阶段。
  3. 使用 ifNull 初始化空 roleIds[](因为所有用户都没有该字段)。

试试这个查询:

db.getCollection('users').aggregate([
    {
        $match: {
            'username': 'foo@bar',
        }
    },
    {
        $lookup: {
            from: 'roles',
            let: { 'roleIds': { $ifNull: ["$roleIds", []] } },
            as: 'roles',
            pipeline: [
                {
                    $match: {
                        $expr: { $in: ["$_id", "$$roleIds"] }
                    }
                },
                {
                    $lookup: {
                        from: 'permissions',
                        let: { 'permissionId': "$permissionIds" },
                        pipeline: [
                            {
                                $match: {
                                    $expr: { $eq: ["$_id", "$$permissionId"] }
                                }
                            },
                            {
                                $project: {
                                    name: 1
                                }
                            }
                        ],
                        as: 'permissions'
                    }
                },
                {
                    $project: {
                        name: 1,
                        permissions: 1
                    }
                }
            ]
        }
    }
]);