问题
I have two collections in MongoDB 3.6:
users: [
{name: "John", allowedRoles: [1, 2, 3]},
{name: "Charles", allowedRoles: [1]},
{name: "Sarah", isAdmin: true}
]
roles: [
{_id: 1, name: "Foo", description: "This role allows to foo the blargs"},
{_id: 2, name: "Bar", description: "..."},
{_id: 3, name: "Doh", descripcion: "..."}
]
I'm very new to MongoDB; I just figured out how to query an user and join all the data from his roles, using the $lookup aggregation stage:
db.users.aggregate([{
"$match": { "name": "John" } // Or without this $match part, to get all users
},{ //
"$lookup": {
"from": "roles",
"localField": "allowedRoles",
"foreignField": "_id",
"as": "roles"
}
}]);
It works for my regular users, who have an array of allowed roles IDs. I have also administrator users, which can access all existing roles, but don't have the allowedRoles
array (it would be a burden to maintain, since new roles will be created frequently). So, instead of specifying the join fields, I do a $lookup
with an empty pipeline, to get the cartesian product of both collections:
db.users.aggregate([{
"$match": { "name": "Sarah" }
},{
"$lookup": {
"from": "roles",
"pipeline": [],
"as": "roles"
}
}]);
Is there any way to have both, with a single query? With a conditional expression or something?
In an SQL database, I would simply include the condition in the join:
select users.*, roles.*
from users
left join users_x_roles inter on users.id = inter.user_id
left join roles on inter.role_id = roles.id or users.is_admin = 1;
-- ^^^^^^^^^^^^^^^^^^^^^
回答1:
You can use below aggregation
$expr allows you use aggregation operator inside it. So you can easily use $cond aggregation for the users who has allowedRoles
and who hasn't
db.users.aggregate([
{ "$match": { "name": "Charles" }},
{ "$lookup": {
"from": "roles",
"let": { "ar": "$allowedRoles" },
"pipeline": [
{ "$match": {
"$expr": {
"$cond": [
{ "$eq": [{ "$type": "$$ar" }, "missing"] },
{},
{ "$in": ["$_id", "$$ar"] }
]
}
}}
],
"as": "roles"
}}
])
来源:https://stackoverflow.com/questions/53711144/conditional-lookup-in-mongodb