- push from the start of an array
- push from the end of an array
- push multiple elements at once
- push to an array and slice
- push to an array and sort
- avoid gotchas
In the most general case, you can push an element to the end of the array (i.e., append) by performing an update with the $push operator. In the example below we use it to append an 'i' to the alphabet array.
Push from the start of the array
A non-negative $position value describes the position a value will be pushed to by counting from the start, i.e. the left side of an array. In the above example, the position value is 8. Given this position value, MongoDB pushes the new element 'i' to the 8th position in the 0-indexed array alphabet which is between the 'h' and the 'j' .
Push from the end of the array
With MongoDB's 3.6 release, there is additional functionality for inserting into an array: you can now give negative values to the $position modifier. The above update could now also be done like this:
A negative $position value describes the position a value will be pushed to by counting from the end, i.e. the right side of an array. In this code snippet, the $position modifier was assigned the value -1. The negative number indicates to MongoDB to start counting from the right and insert the element before the last element in this case. To insert before the n last elements you would use -n as the position value.
In scenarios where you know you need to insert an object before the n last elements in an array, the option of specifying the position by counting from the right simplifies writing and reading these operations.
Push multiple elements at once
The modifier $each allows you to push each element from an array of elements to a document's array at a specified position.
Let's break down what happens when you push ['f', 'g', 'h'] by considering each element from the array as its own stage. In this case 'f' would be pushed to the specified position -2 first, then 'g', and, lastly, 'h'. The element ending up in the position -2 after all elements are inserted is therefore 'h'. The preceding elements are in positions -3 and -4. Overall, the elements of the array are inserted in order.
Push onto an array while slicing
Now let's look at some more options of modifying an array while pushing. Let's consider an online store that keeps track of the last 3 items a user viewed. When adding a new item, $slice can be used to limit the number of array elements:
By not using the $position modifier, the operation pushes the item 'Dates' to the end of the array. To keep the array to only the 3 most recent items, you then slice the recent-items. The negative value -3 for the $slice modifier results in an array with the last 3 elements remaining in the array.
If instead you need to keep the first n elements of the array, you can specify a positive value n for the $slice modifier. Specifying 0, on the other hand, will result in your result array being an empty array.
If you are backfilling data, for example, you can also specify a $position modifier. Note that the $slice modifier takes effect after the element(s) are pushed. To use $slice to just slice an array without adding new elements you can specify $each: [ ] .
Push onto an array while sorting
Apart from slicing you may also want to use $sort to sort an array or insert into an array while keeping it sorted. You can use it along with $slice and $position. Note that specifying any position is futile, since the sorting will move the element as needed. The order in which $sort, $position, and $slice are applied is: first $position, then $sort, and lastly $slice.
Let's consider a game that stores its top 10 highest scores. We will use slice and sort to add a new high score while keeping the list sorted and limited to 10 scores:
The update query adds the new score 72 and the array is then sorted before it is sliced to the specified 10 elements. In this example, the array is sorted based on the numbers it contains. However, if you have documents within an array you can also sort based on a field within those documents.
$position = -0
You may think that this would add the element to the end of the array but alas -0 is the same as 0 and therefore the element will be pushed to the beginning of the array.
Removing the $position modifier results in the element being added to the end of the array.
$position = -999999999
If the absolute value of a negative position value is greater or equal to the length of the array, the element being added will be pushed to the beginning of the array.
Be aware that push operations that specify a position rewrite the entire array which can lead to high CPU usage during updates. The rewriting of arrays results in many index key updates for indexes on those arrays, larger oplog entries, and consequently a shorter oplog window.
In general large arrays can be problematic for performance. For very fast moving array contents, consider breaking arrays out into their own collections.
To read more about this check out the documentation: docs.mongodb.com/manual/reference/operator/update/push/.
Naomi Pentrel is a Developer Advocate at mLab and a full-stack pythonista with a focus on improving developer workflows. She has previously worked at companies such as Google, Microsoft, and Bloomberg. When not at work or a organizing Smooth DevOps, Naomi is an avid Pokémon master and a slayer of houseplants.