我有3个模型(项目,组织,用户),其架构如下所示。我正在使用mongo版本4.2.0和Moongoose版本5.1.1。
问题
给特定的用户,我如何查询他们有权访问的所有项目:
通过项目本身的直接角色
或通过该项目所属组织的直接角色
用户可以在组织中发挥作用,但在其项目中可能没有。尽管如此,查询仍应能够获取这些项目(用户具有上级访问权限)。
示例
Projects
[
{
"_id" : ObjectId("1184f3c454b1fd6926c324fd"),
"organizationId" : ObjectId("1284f3c454b1fd6926c324fd"),
"roles" : [
{
user: ObjectId("1314f3c454b1fd6926c324fd"),
role: 'Bar'
}
]
},
{
"_id" : ObjectId("1172f3c454b1fd6926c324fd"),
"organizationId" : ObjectId("1284f3c454b1fd6926c324fd"),
"roles" : [
{
user: ObjectId("1313f4c584b1fd6926c324fd"),
role: 'Bar'
}
]
}
]
Organizations
{
"_id" : ObjectId("1284f3c454b1fd6926c324fd"),
"roles" : [
{
user: ObjectId("1314f3c454b1fd6926c324fd"),
role: 'Bar'
}
]
}
Users
{
"_id" : ObjectId("1314f3c454b1fd6926c324fd"),
"name": "Foo"
}
[Notes
这两个项目属于同一组织。
用户“ Foo”属于此组织,但只能直接访问其项目之一。
有问题的查询应为用户“ Foo”返回两个项目。
应该将两个不同的查询合并吗?
使用aggregation
管道,您可以实现此查询:
db.Projects.aggregate([
{
$lookup: {
from: "Organizations",
localField: "organizationId",
foreignField: "_id",
as: "organization"
}
},
{
$match: {
$or: [
{
"roles.user": varSpecificUserId
},
{
"organization.roles.user": varSpecificUserId
}
]
}
}
]);
这里是EXPLANATIONS,来自以下数据库数据:
Projects
[
{
"_id": "pro0",
"organizationId": "org0",
"roles": []
},
{
"_id": "pro2",
"organizationId": "org1",
"roles": []
},
{
"_id": "pro3",
"organizationId": "org0",
"roles": [
{
user: "usr2",
role: "Foo"
}
]
}
]
Organizations
[
{
"_id": "org0",
"roles": [
{
user: "usr0",
role: "Foo"
}
]
},
{
"_id": "org1",
"roles": [
{
user: "usr1",
role: "Bar"
}
]
}
],
Users
[{
"_id": "usr0",
"name": "User0"
},
{
"_id": "usr1",
"name": "User1"
},
{
"_id": "usr2",
"name": "User2"
},
{
"_id": "usr3",
"name": "User3"
}
]
}
varSpecificUserId
specific user
'_id。$lookup
使用来自localField
集合的Projects
与来自foreignField
集合的Organizations
匹配的另一个集合。$lookup
的结果是所有Organizations
的数组,如果每个organizationId
都与Project
匹配。使用organisation
对象的as
关键字将该数组存储在$lookup
。这是前查询对象在此步骤:{
"_id": "pro0",
"organization": [
{
"_id": "org0",
"roles": [
{
"role": "Foo",
"user": "usr0"
}
]
}
],
"organizationId": "org0",
"roles": []
},
organization
现在附加到Project
,我们具有执行查询的所有信息:
$match
步骤将在Projects
数组中具有匹配的user
的roles
与varSpecificUserId
变量OR保持在user
的organization
中的匹配roles
数组。这是使用varSpecificUserId = "usr0"
的最终查询结果:
[
{
"_id": "pro0",
"organization": [
{
"_id": "org0",
"roles": [
{
"role": "Foo",
"user": "usr0"
}
]
}
],
"organizationId": "org0",
"roles": []
},
{
"_id": "pro3",
"organization": [
{
"_id": "org0",
"roles": [
{
"role": "Foo",
"user": "usr0"
}
]
}
],
"organizationId": "org0",
"roles": [
{
"role": "Foo",
"user": "usr2"
}
]
}
]
如果您已经有数据库中的数据,则可以使用https://mongoplayground.net/来处理mongo查询或MongoDB Compass中的新聚合工具。