MongoDB $push appends values to an array in an update, while aggregation $push collects expression results into an array across input documents.
The identical name hides two different operations. Both are useful; neither is permission to keep every event a product has ever seen inside one document.
Table of contents
- Append one value with the update operator
- Use modifiers for several values and bounded history
- Prevent duplicates with the right operator
- Do not confuse update push with aggregation push
- Choose embedding or a child collection deliberately
- How this fits the rest of the stack
- FAQ
Append one value with the update operator
In an update, $push adds a value to an array field. If the field does not exist, MongoDB creates the array. If the field exists with a non-array value, the operation fails rather than guessing how to remodel the document.
db.projects.updateOne(
{ _id: projectId },
{ $push: { deploys: { id: deployId, status: 'queued' } } }
)
Match the document narrowly and inspect the update result. An acknowledged command with zero matched documents is not a successful business operation just because no exception was raised.
Use modifiers for several values and bounded history
Combine $each with $position, $sort, and $slice to add several values, order the resulting array, and retain only a bounded window. Modifier processing follows MongoDB’s defined order rather than the textual order in the update.
db.projects.updateOne(
{ _id: projectId },
{ $push: { deploys: {
$each: newDeploys,
$sort: { createdAt: -1 },
$slice: 20
} } }
)
Bounding an embedded recent-history list is practical. Keeping an unbounded event stream in one document approaches the document-size limit, increases write cost, and creates a hot record.
Prevent duplicates with the right operator
$push does not check whether a value already exists. Use $addToSet for exact-value set semantics, or model items with identifiers and enforce idempotency in the update filter or a separate collection. Embedded-document equality can be stricter than the business definition of duplicate.
Retryable requests make this important. A client timeout can hide a successful first write, and a blind retry can append the same event again. Give operations stable idempotency keys when duplicates matter.
Do not confuse update push with aggregation push
Inside aggregation stages such as $group or $setWindowFields, $push is an accumulator. It gathers the value of an expression for input documents into an output array. It does not mutate the source documents.
db.deploys.aggregate([
{ $sort: { createdAt: 1 } },
{ $group: { _id: '$projectId', statuses: { $push: '$status' } } }
])
Sort before grouping when array order matters. Without an explicit order, a report should not pretend the database promised one.
Choose embedding or a child collection deliberately
Embed small, bounded values that are usually read with the parent. Use a separate collection for unbounded history, independently queried records, high write concurrency, or data with its own lifecycle and indexes.
Monitor document size, update latency, write conflicts, and array length. A document model is an operational choice. It should reflect how the product reads and changes data, not merely how convenient the first JSON object looked.
How this fits the rest of the stack
If the document model belongs to a production service, compare the MongoDB capacity, API, storage, worker, and transfer costs in the RunxBuild hosting calculator. Then use the RunxBuild dashboard to deploy the application with its database path visible.
Useful related references:
- Install MongoDB on Ubuntu: Official Repo, systemd, and 7.0 Setup
- Mongo Express: The Web Admin for MongoDB That Shouldn’t Run in Production
- Databases on RunxBuild
FAQ
What does MongoDB push do?
In updates, $push appends a value to an array field. In aggregation, $push collects expression results into an array without mutating source documents.
How do I push multiple values?
Use $push with the $each modifier and an array of values.
How do I avoid duplicate array values?
Use $addToSet for exact-value uniqueness or design an idempotent update around a stable item identifier.
Can push keep only the latest items?
Yes. Combine $each, $sort, and $slice to order the resulting array and retain a bounded number of entries.
When should I avoid an embedded array?
Use a child collection for unbounded growth, independent queries, high concurrent writes, separate retention, or records needing their own indexes.