MongoDB $push

In MongoDB, you can use the $push operator to append a value to an array.

You can use various modifiers to specify the value’s position in the array, the order of the elements in the array, append multiple values, etc.

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" : [ "M", "L" ] }

And let’s say we want to append a value to the array in document 3.

We can use $push in conjunction with update() to append the value:

db.products.update(
   { _id: 3 },
   { $push: { sizes: "XL" } }
)

Output:

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

Let’s look at the collection again to verify the change:

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" : [ "M", "L", "XL" ] }

Insert the Value at a Certain Position

You can use the $each and $position modifiers to specify where the value should be inserted into the array.

For example, we can use a value of 0 to insert it at the start of the array.

Example:

db.products.update(
   { _id: 3 },
   { 
     $push: { 
        sizes: {
           $each: [ "S" ],
           $position: 0
        }
      } 
    }
)

Output:

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

The $each modifier appends multiple values to the array field. In this case we only inserted one value to the array, however, to use the $position modifier, it must appear with the $each modifier.

Let’s check the collection again:

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" ] }

Append and Sort

Suppose we have a collection with the following documents:

db.players.find()

Result:

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

And suppose we want to append some values to the array in document 3, but we also want to sort the array in ascending order after we’ve appended the value.

We can do this:

db.players.update(
   { _id: 3 },
   { 
     $push: { 
        scores: {
           $each: [ 5, 12 ],
           $sort: 1
        }
      } 
    }
)

Output:

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

Now when we view the collection, we can see that the third document has been modified accordingly.

db.players.find()

Result:

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

To sort it in descending order, use $sort: -1.

Slice the Array

You can use the $slice modifier to limit the number of elements in the array.

For example, let’s add another value to the array, but then slice the array to a certain number of elements.

db.players.update(
   { _id: 3 },
   { 
     $push: { 
        scores: {
           $each: [ 3 ],
           $slice: 3
        }
      } 
    }
)

Output:

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

Now let’s check the collection again:

db.players.find()

Result:

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

In this case, the array was sliced, but the value that we appended didn’t even end up in the final array. This is because the value was appended to the array and we didn’t use a $sort operation, and so the value remained at the end of the array before the array was sliced to its first three elements.

Here it is again, except this time with the $sort modifier.

db.players.update(
   { _id: 3 },
   { 
     $push: { 
        scores: {
           $each: [ 3 ],
           $sort: 1,
           $slice: 3
        }
      } 
    }
)

Output:

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

Check the collection:

db.players.find()

Result:

{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 8 ] }

Append Value only if it Doesn’t Exist

If you want the value to be appended only if it doesn’t already exist in the array, then consider using the $addToSet operator.