如何将两个不同查询的结果与猫鼬结合起来?
How to combine the results of two different queries with mongoose?
我有 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" 属于该组织,但只能直接访问其中一个项目。
有问题的查询应该 return both projects for the user "Foo".
是否应该合并两个不同的查询?
使用 aggregation
管道,您可以使用这个:
db.Projects.aggregate([
{
$lookup: {
from: "Organizations",
localField: "organizationId",
foreignField: "_id",
as: "organization"
}
},
{
$match: {
$or: [
{
"roles.user": varSpecificUserId
},
{
"organization.roles.user": varSpecificUserId
}
]
}
}
]);
这是来自以下数据库数据的解释:
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
使用 Projects
集合中的 localField
与 Organizations
集合中的 foreignField
匹配来查询其他集合。
$lookup
的结果是所有 Organizations
与 organizationId
匹配的数组,如果每个 Project
。该数组使用 $lookup
对象的 as
关键字存储在 organisation
处。这是一个前任。这一步查询对象的数量:
{
"_id": "pro0",
"organization": [
{
"_id": "org0",
"roles": [
{
"role": "Foo",
"user": "usr0"
}
]
}
],
"organizationId": "org0",
"roles": []
},
organization
现在附加到 Project
,我们有执行查询的所有信息:
- 通过项目本身的直接角色
- 或通过项目所属组织中的直接角色
$match
步骤保留 Projects
在 roles
数组中具有匹配的 user
和 varSpecificUserId
变量 OR organization
的 roles
数组中的匹配 user
。这是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 的新聚合工具。
我有 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" 属于该组织,但只能直接访问其中一个项目。
有问题的查询应该 return both projects for the user "Foo".
是否应该合并两个不同的查询?
使用 aggregation
管道,您可以使用这个:
db.Projects.aggregate([
{
$lookup: {
from: "Organizations",
localField: "organizationId",
foreignField: "_id",
as: "organization"
}
},
{
$match: {
$or: [
{
"roles.user": varSpecificUserId
},
{
"organization.roles.user": varSpecificUserId
}
]
}
}
]);
这是来自以下数据库数据的解释:
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
使用Projects
集合中的localField
与Organizations
集合中的foreignField
匹配来查询其他集合。$lookup
的结果是所有Organizations
与organizationId
匹配的数组,如果每个Project
。该数组使用$lookup
对象的as
关键字存储在organisation
处。这是一个前任。这一步查询对象的数量:
{
"_id": "pro0",
"organization": [
{
"_id": "org0",
"roles": [
{
"role": "Foo",
"user": "usr0"
}
]
}
],
"organizationId": "org0",
"roles": []
},
organization
现在附加到Project
,我们有执行查询的所有信息:- 通过项目本身的直接角色
- 或通过项目所属组织中的直接角色
$match
步骤保留Projects
在roles
数组中具有匹配的user
和varSpecificUserId
变量 ORorganization
的roles
数组中的匹配user
。这是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 的新聚合工具。