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
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:
I solved it with my own function. If you want to update specified field in document you need to address it clearly.
Example:
If you want to update param2 only, it's wrong to do:
You must use:
So i wrote a function something like that:
use $set do this process
It looks like you can set isPartialObject which might accomplish what you want.
The best solution is to extract properties from object and make them flat dot-notation key-value pairs. You could use for example this library:
https://www.npmjs.com/package/mongo-dot-notation
It has
.flatten
function that allows you to change object into flat set of properties that could be then given to $set modifier, without worries that any property of your existing DB object will be deleted/overwritten without need.Taken from
mongo-dot-notation
docs:And then it forms perfect selector - it will update ONLY given properties. EDIT: I like to be archeologist some times ;)
Make an update object with the property names including the necessary dot path. ("somekey."+ from OP's example), and then use that do the update.