I have a nested mongo array
{
"_id": 1,
"date": "2024-09-30",
"employees": [
{
"_id": 101,
"name": "John Doe",
"company": "ABC Corp",
"department": "HR",
"salary": 50000,
"contactNumber": "123-456-7890"
},
{
"_id": 102,
"name": "A",
"company": "XYZ Corp",
"department": "HR",
"salary": 500100,
"contactNumber": "1333-456-7890"
},
{
"_id": 103,
"name": "B",
"company": "XYZ Corp",
"department": "HR",
"salary": 500100,
"contactNumber": "1333-456-7890"
}
]
}
I need to update the salary of 101 and also add new memeber 104. How can i do in single update?
I am able to do with 2 updates. One to update 101’s salary using ArrayFilters and another is to $push 104 to array. Below are the queries,
db.collection.updateOne(
{ _id: 1 }, // Match the document with _id: 1
{
$set: { "employees.$[emp].salary": 60000 } // Set the new salary for employee with _id: 101
},
{
arrayFilters: [ { "emp._id": 101 } ] // Array filter to target the specific employee with _id: 101
}
)
db.collection.updateOne(
{ _id: 1 }, // Match the document with _id: 1
{
$push: {
employees: {
_id: 104,
name: "New Employee",
company: "New Corp",
department: "HR",
salary: 70000,
contactNumber: "987-654-3210"
}
}
}
)
Is there any way I can do both adding new employee and updating existing employee in same query.?
I think I can use aggregate to do so. but which is better in case of performance?
2
Answers
This can’t be be in a single update query – "Updating the path ’employees’ would create a conflict at ’employees’" – which happens because both operations are on the ’employees’ field. However, if you were pushing to a different field like
newEmployees
, then it would work. The only difference in those two linked queries is the field for$push
.Anyway, wrt to doing both together with an aggregation, one agg would be faster than two separate updates but probably not worth the complexity. Does a new employee need to be added every time another employee’s salary changes?
If you need "both work or both fail" behaviour, then consider using transactions.
You can do the followings in an update with aggregation pipeline.
$concatArrays
to append the new 104 entry to the end of theemployees
array$map
to iterate through the resulting array. Conditionally update the array entry with$mergeObjects
if the entry’s id is 101Mongo Playground