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
文档,而不管它是否实际上是一个连接。
我是不是马上做错了什么??
您的查询中存在以下错误:
- 在两次查找中,您都将错误的变量传递给
let
内的 pipeline
。
- 管道内缺少执行实际连接操作的
$match
阶段。
- 使用
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
}
}
]
}
}
]);
我有一个用户索引
[{
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
文档,而不管它是否实际上是一个连接。
我是不是马上做错了什么??
您的查询中存在以下错误:
- 在两次查找中,您都将错误的变量传递给
let
内的pipeline
。 - 管道内缺少执行实际连接操作的
$match
阶段。 - 使用
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
}
}
]
}
}
]);