4

I have a document in this form

{
   "firstName": "John",
   "lastName": "Doe",
   "preferences": {
      "xxx": true,
      "yyy": false,
      "zzz": true
   }
}

I want to update specific fields in the preferences embedded document. If I use the $set operand in the following way

db.users.update({name: "John"}, {$set: {preferences: {"xxx": false}}})

the preferences document is completely replaced, so I get this

{
   "firstName": "John",
   "lastName": "Doe",
   "preferences": {
      "xxx": false
   }
}

while I would like to obtain this

{
   "firstName": "John",
   "lastName": "Doe",
   "preferences": {
      "xxx": false,
      "yyy": false,
      "zzz": true
   }
}

I cannot use:

db.users.update({name: "John"}, {$set: {"preferences.xxx": false}})

because I don't know which specific field I'm going to update, I only have as input an object that may or may not contain each field of the preferences document.

tano
  • 836
  • 1
  • 10
  • 25

1 Answers1

2

Try creating the update object prior to the update. For instance, if you have as input the object {"xxx": false, "abc": false}, you could use JavaScript's bracket notation to create the update object as follows:

var input = {"xxx": false, "abc": false},
        update = { "$set": {} },
        keys = Object.keys(input),
        query = {"name": "John"};
keys.forEach(function(key){ update["$set"]["preference."+key] = input[key]; });
printjson(update); // {"$set":{"preference.xxx":false,"preference.abc":false}} 


db.users.update(query, update);
chridam
  • 100,957
  • 23
  • 236
  • 235