MongoDB $addToSet

In MongoDB, the $addToSet operator adds a value to an array unless the value is already present in the array.

It’s similar to the $push operator, except that $push adds the value even if the value is already present.

Example

Suppose we have a collection called products with the following documents:

db.products.find()

Result:

{ "_id" : 1, "product" : "Bat", "sizes" : [ "S", "M", "L" ] }
{ "_id" : 2, "product" : "Hat", "sizes" : [ "S", "L", "XL" ] }
{ "_id" : 3, "product" : "Cap", "sizes" : [ "S", "M", "L", "XL" ] }

We can use $addToSet to append a value to one of those arrays.

Example:

db.products.update(
   { _id: 1 },
   { $addToSet: { sizes: "XL" } }
)

Output:

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

Let’s take another look at our collection to verify the change:

db.products.find()

Result:

{ "_id" : 1, "product" : "Bat", "sizes" : [ "S", "M", "L", "XL" ] }
{ "_id" : 2, "product" : "Hat", "sizes" : [ "S", "L", "XL" ] }
{ "_id" : 3, "product" : "Cap", "sizes" : [ "S", "M", "L", "XL" ] }

Duplicate Values

If you try to insert a value that already exists in the array, nothing happens. In other words, $addToSet only inserts the value if it doesn’t already exist.

Here’s an example of attempting to insert a value that already exists.

db.products.update(
   { _id: 1 },
   { $addToSet: { sizes: "XL" } }
)

Output:

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

This message tells us that there was one matching document (i.e. the document with an _id of 1), but there were no modifications.

In the previous example we saw "nModified" : 1, but in this example we see "nModified" : 0. That’s because the value didn’t exist when we inserted it in the previous example, but in this example it already exists.

We can verify this by looking at the collection again:

db.products.find()

Result:

{ "_id" : 1, "product" : "Bat", "sizes" : [ "S", "M", "L", "XL" ] }
{ "_id" : 2, "product" : "Hat", "sizes" : [ "S", "L", "XL" ] }
{ "_id" : 3, "product" : "Cap", "sizes" : [ "S", "M", "L", "XL" ] }

Add Multiple Values

You can use the $each modifier to append multiple values to an array.

Example:

db.products.update(
   { _id: 2 },
   { 
     $addToSet: { 
        sizes: {
           $each: [ "XXL", "XXXL" ]
        }
      } 
    }
)

Output:

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

Now let’s check the collection again:

db.products.find()

Result:

{ "_id" : 1, "product" : "Bat", "sizes" : [ "S", "M", "L", "XL" ] }
{ "_id" : 2, "product" : "Hat", "sizes" : [ "S", "L", "XL", "XXL", "XXXL" ] }
{ "_id" : 3, "product" : "Cap", "sizes" : [ "S", "M", "L", "XL" ] }

We can see that the two values were appended to the array in document 2 as expected.

Add an Array to the Array

You can also append a whole array to the array. When you do this, the whole array is appended as its own separate array.

Suppose we have a collection like this:

db.foo.find()

Result:

{ "_id" : 1, "bar" : [ 1, 5, 3 ] }
{ "_id" : 2, "bar" : [ 8, 17, 18 ] }
{ "_id" : 3, "bar" : [ 15, 11, 8 ] }

We can append an array to an array like this:

db.foo.update(
   { _id: 1 },
   { $addToSet: { bar: [ 7, 8, 9] } }
)

Output:

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

Check the collection:

db.foo.find()

Result:

{ "_id" : 1, "bar" : [ 1, 5, 3, [ 7, 8, 9 ] ] }
{ "_id" : 2, "bar" : [ 8, 17, 18 ] }
{ "_id" : 3, "bar" : [ 15, 11, 8 ] }