mongodbmongodb-java

How do I partially update an object in MongoDB so the new object will overlay / merge with the existing one


Given this document saved in MongoDB

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2",
        param3 : "val3"
   }
}

An object with new information on param2 and param3 from the outside world needs to be saved

var new_info = {
    param2 : "val2_new",
    param3 : "val3_new"
};

I want to merge / overlay the new fields over the existing state of the object so that param1 doesn't get removed

Doing this

db.collection.update(  { _id:...} , { $set: { some_key : new_info  } } 

Will lead to MongoDB is doing exactly as it was asked, and sets some_key to that value. replacing the old one.

{
   _id : ...,
   some_key: { 
      param2 : "val2_new",
      param3 : "val3_new"
   }
}

What is the way to have MongoDB update only new fields (without stating them one by one explicitly)? to get this:

{
   _id : ...,
   some_key: { 
        param1 : "val1",
        param2 : "val2_new",
        param3 : "val3_new"
   }
}

I'm using the Java client, but any example will be appreciated


Solution

  • If I understand the question correctly, you want to update a document with the contents of another document, but only the fields that are not already present, and completely ignore the fields that are already set (even if to another value).

    There is no way to do that in a single command.

    You have to query the document first, figure out what you want to $set and then update it (using the old values as a matching filter to make sure you don't get concurrent updates in between).


    Another reading of your question would be that you are happy with $set, but do not want to explicitly set all fields. How would you pass in the data then?

    You know you can do the following:

    db.collection.update(  { _id:...} , { $set: someObjectWithNewData }