MongoDB $setOnInsert

The MongoDB $setOnInsert field update operator can be used to insert a specific value during an upsert.

If an update operation results in a new document being inserted (i.e. an upsert), then the $setOnInsert operator takes effect, otherwise it has no effect.

Example

Suppose we have a collection called dogs with the following document:

{ "_id" : 1, "name" : "Wag", "weight" : 11, "height" : 30 }

And we run the following update() command to update a document that doesn’t exist in the collection:

db.dogs.update(
  { _id: 2 },
  {
     $set: { weight: 50, height: 40 },
     $setOnInsert: { name: "Bark" }
  },
  { upsert: true }
)

This will result in the following output:

WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 2 })

Which tells us that one document was upserted.

Let’s check the collection:

db.dogs.find()

Result:

{ "_id" : 1, "name" : "Wag", "weight" : 11, "height" : 30 }
{ "_id" : 2, "height" : 40, "name" : "Bark", "weight" : 50 }

We can see that document 2 has been inserted, and it includes the field/value that we provided for the $setOnInsert operator (i.e. name: "Bark").

When the Document Does Exist (i.e. No Upsert)

Now let’s try to update the document we just upserted. Let’s use the same statement as in the previous example, but with different values.

db.dogs.update(
  { _id: 2 },
  {
     $set: { weight: 55, height: 45 },
     $setOnInsert: { name: "Fluffy" }
  },
  { upsert: true }
)

Output:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

This time, one document matched and was updated. Nothing was upserted.

Let’s check the collection again.

db.dogs.find()

Result:

{ "_id" : 1, "name" : "Wag", "weight" : 11, "height" : 30 }
{ "_id" : 2, "height" : 45, "name" : "Bark", "weight" : 55 }

So in this case, the weight and height fields were updated, but the name field wasn’t.

The reason the name field wasn’t updated is because an upsert wasn’t being performed. The $setOnInsert operator only specifies the field/value to be set when the update operation results in a new document being inserted (i.e. an upsert).