A curious case of MongoDB updates with upsert:true

One of the benefits of being a TA for M102 course is that you get to learn even more by answering questions. Because some questions are fascinating.

Yesterday we had a very interesting case that puzzled even those folks who are usually able to answer anything in the forum. There was some virtual head scratching (or at least I’m imagining it), and we decided to ask the 10gen team if they can shed some light on this.

Here’s the scenario, where we are starting with an empty collection:

db.test.update({_id : "Jane"}, {"count" : 1}, true)
db.test.update({_id : "Jane2"}, {$set: {"count" : 1}}, true)

db.test.find()

{ "_id" : ObjectId("510aa62cbb530b24318c93d4"), "count" : 1 }
{ "_id" : "Jane2", "count" : 1 }

As we see, in both update statements, the “upsert” option is set to true.

The result of the first statement is a document with an _id field assigned by default by MongoDB, even though we specified _id:”Jane”.

However, the result of the second statement is the document with the _id that we specified – so it’s a different outcome when we use “$set” operation.

And here’s the explanation (from MongoDB docs):

If the argument includes only field and value pairs, the new document contains the fields and values specified in the argument. If the argument includes only update operators, the new document contains the fields and values from argument with the operations from the argument applied.

Link: http://docs.mongodb.org/manual/applications/update/

Then Andrew also explained in the discussion forum:

The behavior of the update operator depends on what is the second positional document. If you put in set operator or push operator, then the db will insert a document that has both the fields that are set in the selector and is the result of applying your pushes and sets.

So this behavior is expected, but still makes a very interesting case. Live and learn, my friends!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s