0

Let say we have a document in mongodb

{
  id : 101,
  addresses : [
    {
      id: 1,
      suite: "flat 201",
      street: "north street"
      city: "london",
      country: "uk"
    }
  ]
}

i want to update multiple properties of the object at once without replacing whole object. For example :

const newAddress = {
  id:1,
  suite: "flat 301",
  street: "south street"
} 


userCollection.updateOne(
  {id : 101},
  { $set : {"addresses.$[address]" : newAddress } },
  {arrayFilters: [{address.id : newAddress.id}]}
)

This operation sets the object with new fields instead of updating only the given fields.

9
  • 1
    you need to specify all properties name, "addresses.$[address].suite" : newAddress.suite, "addresses.$[address].street" : newAddress.street. Commented Sep 28, 2022 at 14:13
  • what if we have many many fields.. and we can't pre define which fields user will update. Commented Sep 28, 2022 at 14:16
  • you have to prepare that logic on the client side, but the update query requires separate properties otherwise it will replace the whole object. Commented Sep 28, 2022 at 14:17
  • @turivishal ok.. looks like we have to perform a loop for each field Commented Sep 28, 2022 at 14:21
  • yes, loop that object's properties and prepare the object that the update query requires. Commented Sep 28, 2022 at 14:23

1 Answer 1

1

When you update an object's properties, it must be required to specify each one by one, and if the properties are dynamic then you have to prepare a payload for an update on client side,

I assume you are using javascript,

const newAddress = {
  id:1,
  suite: "flat 301",
  street: "south street"
};

let set = {};
for (let n in newAddress) {
  set["addresses.$[address]."+n] = newAddress[n];
}

console.log(set);

// prepared update object
{
 "addresses.$[address].id": 1,
 "addresses.$[address].suite": "flat 301",
 "addresses.$[address].street": "south street"
}

You can pass set to update part in query,

userCollection.updateOne(
  { id : 101 },
  { $set : set },
  { arrayFilters: [{ "address.id" : newAddress.id }] }
)

You can do this directly in an update query but you have to use an update with an aggregation pipeline and I don't recommend this because it requires multiple expression operators and it is expensive.

Sign up to request clarification or add additional context in comments.

8 Comments

should i select nested array's object using arrayFilters or multiple query operator like ({id:1, "address.id": newAddress.id}). what will scan less docs to find it?
yes you can filter nested array's object by arrayFilters.
i know i can use arrayFilters.. but which way is more efficient between arrayFilters and multiple query parameter?
i am not exactly getting what is multiple query parameter?
then yes you can use that using $ positional update, no need to use arrayFilters.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.