Question

I would like to use findAndModify to upsert the fields of an embedded document. For example, if I were to insert this document.

{
   'name':'Goku',
   'level':9000,
   'family':{
      'son':'Grandpa Gohan',
      'wife':'Chi Chi'
   }
}

Then at some later point, insert the following document:

{
   'name':'Goku',
   'type':'Super Saiyan',
   'family':{
      'son':'Gohan',
      'father':'Bardock'
   }
}

The desired final result would be:

{
   'name':'Goku',
   'level':9000,
   'type':'Super Saiyan',
   'family':{
      'son':'Gohan',
      'father':'Bardock',
      'wife':'Chi Chi'
   }
}

I've tried to implement this in Java with the code below to no avail. Is there any built-in that serves to achieve the desired result above?

String json = "{'name':'Goku', 'level':9000, 'family':{'son':'Grandpa Gohan', 'wife':'Chi Chi'} }";
DBObject document = (DBObject) JSON.parse(json);
BasicDBObject update = new BasicDBObject("$set", document);
BasicDBObject query = new BasicDBObject().append("name", document.get("name"));
collection.findAndModify(query, null, null, false, update, false, true);

json = "{'name':'Goku', 'type':'Super Saiyan', 'family':{'son':'Gohan', 'father':'Bardock'} }";
document = (DBObject) JSON.parse(json);
update = new BasicDBObject("$set", document);
query = new BasicDBObject().append("name", document.get("name"));
collection.findAndModify(query, null, null, false, update, false, true);

-- EDIT --

Neil Lunn has posted the correct answer below. For anyone curious as to what this means in Java, you only need to change one line for the code above in order to achieve the desired result:

[...]

json = "{'name':'Goku', 'type':'Super Saiyan', 'family.son':'Gohan', 'family.father':'Bardock'} }";
[...]
Was it helpful?

Solution

You are on the right track but the problem is that you are ultimately passing in the whole sub-document, and that is overwriting the existing entry.

In order to get what you want, you need to break you update up using "dot notation" similar to this:

db.collection.update(
    { "name": "Goku" },
    {
        "$set": {
            "type": "Super Saiyan",
            "family.son": "Gohan",
            "family.father": "Bardock"
        }
    }
)

So when you fully specify the keys you are not actually replacing the entire sub-document but are rather adding the additional entries.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top