1 / 1
Jan 24

Hello everyone,
I have been struggling with this topic for a while, maybe you have an idea how to solve this better. I am using the NodeJS SKD.

I have an array of objects, something like:

{ array: [ { name: "Obj1" }, { name: "Obj2" }, { name: "Obj3" } ], } ``` I want to (a) update the property of a single array element and (b) after the update insert a new element into the array. Ideally, I would like to do this on one update operation, to save roundtrips and to avoid an inconsistent state. What I found is, that updating works fine, as long as I do not use an aggregation: ` const { insertedId } = await col.insertOne({ array: [{ name: "Obj1" }, { name: "Obj2" }, { name: "Obj3" }], }); await col.updateOne( { _id: insertedId, }, { $set: { "array.1.name": "Update second array element only" }, }, ); ` The snippet above works fine and only updates the second array element. BUT if I want to do the same in an aggregation, it does not work anymore: ` const { insertedId } = await col.insertOne({ array: [{ name: "Obj1" }, { name: "Obj2" }, { name: "Obj3" }], }); await col.updateOne( { _id: insertedId, }, [ { $set: { "array.1.name": "Update second array element only" }, }, ], ); ` This statement will update every field in the array, create a new object with the name 1 and a property called name: `` { "_id": "67939109ca5e4686dc8f2c91", "array": [ { "1": { "name": "Update second array element only" }, "name": "Obj1" }, { "1": { "name": "Update second array element only" }, "name": "Obj2" }, { "1": { "name": "Update second array element only" }, "name": "Obj3" } ] } ` The only alternative that I have found, is to use a combination of $`arrayElemAt` with `$mergeObject` to select and update the array element in question and then use `$concantArray` and `$slice` to construct a new array: ` const { insertedId } = await col.insertOne({ array: [{ name: "Obj1" }, { name: "Obj2" }, { name: "Obj3" }], }); await col.updateOne( { _id: insertedId, }, [ { $set: { array: { $concatArrays: [ [ { $mergeObjects: [ { $arrayElemAt: ["$array", 0] }, { name: "Update first entry only" }, ], }, ], { $slice: ["$array", 1, { $size: "$array" }] }, ], }, }, }, ], ); ` This solution seems to be very complicated, hard to read and extend, and gets very very complicated, if you work with nested arrays , i.e. doing an update in an array in an object of arrays. I also find this very confusing, why does the `$set` behave differently, depending on whether it is part of an aggregation or not. 1. Is this desired behavior? 2. Is there a better way to achieve the same result?