我有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"
}
注释
这两个项目属于同一组织。
用户“ Foo”属于该组织,但只能直接访问其项目之一。
相关查询应为用户“ Foo”返回两个项目。
是否应将两个不同的查询合并?
答案 0 :(得分:1)
使用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
变量{strong> OR roles
的{{1}}数组中的匹配varSpecificUserId
。这是user
的最终查询结果:
organization
如果您已经有数据库中的数据,则可以使用https://mongoplayground.net/来处理mongo查询或MongoDB Compass中的新聚合工具。