In my example project, I have employees under manager. Db schema is like this;
{
"employees": [
{
"name": "Adam",
"_id": "5ea36b27d7ae560845afb88e",
"bananas": "allowed"
},
{
"name": "Smith",
"_id": "5ea36b27d7ae560845afb88f",
"bananas": "not-allowed"
},
{
"name": "John",
"_id": "5ea36b27d7ae560845afb88g",
"bananas": "not-allowed"
},
{
"name": "Patrick",
"_id": "5ea36b27d7ae560845afb88h",
"bananas": "allowed"
}
]
}
In this case Adam is allowed to eat bananas and Smith is not. If I have to give the permission of eating bananas from Adam to Smith I need to perform update operation twice like this:
db.managers.update(
{ 'employees.name': 'Adam' },
{ $set: { 'employees.$.bananas': 'not-allowed' } }
);
and
db.managers.update(
{ 'employees.name': 'Smith' },
{ $set: { 'employees.$.bananas': 'allowed' } }
);
Is it possible to handle this in a single query?
CodePudding user response:
You can use $map
and $cond
to perform conditional update to the array entries depending on the name of the employee. A $switch
is used for potential extension of cases.
db.collection.update({},
[
{
"$set": {
"employees": {
"$map": {
"input": "$employees",
"as": "e",
"in": {
"$switch": {
"branches": [
{
"case": {
$eq: [
"$$e.name",
"Adam"
]
},
"then": {
"$mergeObjects": [
"$$e",
{
"bananas": "not-allowed"
}
]
}
},
{
"case": {
$eq: [
"$$e.name",
"Smith"
]
},
"then": {
"$mergeObjects": [
"$$e",
{
"bananas": "allowed"
}
]
}
}
],
default: "$$e"
}
}
}
}
}
}
])
CodePudding user response:
db.managers.update(
{
$or: [
{"employees.name": "Adam"},
{"employees.name": "Smith"}
]
},
{
$set: {
"employees.$[e].bananas": {
$cond: [{ $eq: ["$e.name", "Adam"] }, "not-allowed", "allowed"]
}
}
},
{
arrayFilters: [{ "e.name": { $in: ["Adam", "Smith"] } }]
}
)