Re: Updating Nested Documents in MongoDB

From: William Byrne III <william.byrne@xxxxxxxxxxx>
To: mongodb-user <mongodb-user@xxxxxxxxxxxxxxxx>
Date: Wed, 27 Apr 2016 15:50:38 -0700 (PDT)
Why ads?


Zeferinix,

You have a document nested inside another document, and you want to update 
some of the nested document fields but leave all other fields at their 
current values. You have a new document that holds just the fields you want 
to update and their new values, and you want to do the update as a single 
command.

A single call to update() 
<https://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update
can set the value of multiple fields, so in that sense this can be done in 
a single command:

// set up target document
db.coll1.insert({ _id : 999,
                embDoc: {f01:"val01",  f02:"val02",  f03:"val03",
                         f04:"val04",  f05:"val05",  f06:"val06",
                         ...
                         f99 : "val99"  }
                });

// new field values
var newVals = {f02:"val2_new",  f04:"val4_new",  f06:"val6_new"};

//
db.coll1.update({_id:999}, {$set: {"embDoc.f02" : newVals.f02,
                                   "embDoc.f04" : newVals.f04,
                                   "embDoc.f06" : newVals.f06}}) ;

You could also findAndModify() 
<https://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/#db.collection.findAndModify
instead of update().

However, I think what the OP for the SO question you link to 
<http://stackoverflow.com/questions/10290621/how-do-i-partially-update-an-object-in-mongodb-so-the-new-object-will-overlay
wanted was a single MongoDB document modifying command 
<https://docs.mongodb.org/manual/tutorial/modify-documents/> that he could 
pass the newVals variable to. He wanted something like this:

db.coll1.update({_id:999}, {$set: {"embDoc" : newVals}});

that didn’t wipe out all the fields which weren’t being updated. He didn’t 
want to have to specify all the “fNN” field names in his call to update 
like I did above. Presumably his newVals was built dynamically and could 
contain a different group of fields (and new values for them) at different 
times, so hard coding them was not a solution.

Here is code that reformats newVals into a JSON document that can be passed 
to $set in an update() command:

// build '{"key1:"value1", "key2:"value2", ... ' string from newVals
var setC = '{' ;
for (var ff in newVal) {
  setC = setC + ' "embDoc.' + ff + '":"newVal.' + ff + '",';
};
// trim end comma and replace with '}'
setC = setC.substring(0, setC.length -1) + '}' ;
// convert string to a JSON object
var setJ = JSON.parse(setC) ;

db.coll1.update({"_id":999}, {$set : setJ});

This is still only one MongoDB update command - the extra code is because 
the change information in the newVals document is not in the right form to 
pass to update().

The best solution overall would be to change the code that sets newVals 
variable equivalent in your application to use this format: 

 var newVals = {"embDoc.f02" : "val2_new",
                 "embDoc.f04" : "val4_new",
                 "embDoc.f06" : "val6_new"
               }

That way it could replace setJ in my second update() command above and 
remove the need for the reformat code, making this the “one command 
solution” you are looking for.

III
------------------------------

William Byrne III


-- 
You received this message because you are subscribed to the Google Groups "mongodb-user"
group.

For other MongoDB technical support options, see: https://docs.mongodb.org/manual/support/
--- 
You received this message because you are subscribed to the Google Groups "mongodb-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mongodb-user+unsubscribe@xxxxxxxxxxxxxxxx.
To post to this group, send email to mongodb-user@xxxxxxxxxxxxxxxx.
Visit this group at https://groups.google.com/group/mongodb-user.
To view this discussion on the web visit https://groups.google.com/d/msgid/mongodb-user/a1d44b82-d37b-4577-afb4-8db7e7107ec3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Why ads?