MongoDB $push Accumulator

Beginner
5 min read
Updated: Oct 2026
4 examples
Live preview

What Is $push?

$push is a MongoDB accumulator for the $group stage. For each group it builds an array of every value—duplicates included—in document arrival order.

Remember
$push = append every value to an array

each document → evaluate expression → append
duplicates? → kept
order? → arrival order at $group (sort first if needed)

vs $addToSet → unique values only
vs $firstN  → only the first N values
UsePrefer
Full history / every occurrence$push
Distinct values only$addToSet
Only the first N values$firstN

How to Use $push in MongoDB

Pass one expression (field or object) inside $group.

  1. Optionally $sort so values append in the order you want.
  2. Put $push inside $group on an output field.
  3. Pass a field path (e.g. "$city") or an object expression.
  4. Choose _id for the group key (store, user, or null).
PieceRequired?Role
$group._idYesGroup key ("$store", null, …)
$pushYesExpression to append each time
ExpressionYes"$field" or { a: "$x", b: "$y" }

Pseudocode

Pseudocode
for each group:
    list = []
    for each document in group (arrival order):
        list.append(evaluate(expression))
    emit { _id: groupKey, field: list }

Cheat Sheet

Keep these facts handy while building arrays in $group.

TopicDetail
Stage$group only (as an accumulator)
Syntax{ $push: "$field" }
DuplicatesKept (every occurrence)
OrderDocument arrival order—use $sort first
vs $addToSet$addToSet drops duplicates
Sample checkstore A cities: New York, New York, Chicago

Live Preview

Watch cities append document by document. Sample orders: A/New York, A/New York, A/Chicago, B/New York.

Simulates appending every city (duplicates kept).

Result
store A + New York → ["New York"]
store A + New York → ["New York", "New York"]
store A + Chicago → ["New York", "New York", "Chicago"]
store B + New York → ["New York"]

[
  { _id: "A", cities: ["New York", "New York", "Chicago"] },
  { _id: "B", cities: ["New York"] }
]

Worked Walkthrough — Push Cities

Four orders, two stores. Watch store A keep New York twice, then append Chicago.

Calculation
Documents:
  { store: "A", city: "New York" }
  { store: "A", city: "New York" }
  { store: "A", city: "Chicago" }
  { store: "B", city: "New York" }

Group store "A":
  [] + "New York" → ["New York"]
  ["New York"] + "New York" → ["New York", "New York"]
  ["New York", "New York"] + "Chicago" → ["New York", "New York", "Chicago"]

Group store "B":
  [] + "New York" → ["New York"]

Output:
  { _id: "A", cities: ["New York", "New York", "Chicago"] }
  { _id: "B", cities: ["New York"] }

MongoDB Examples

We use a tiny orders list. First we push every city per store. Then we contrast $addToSet. Finally we push small objects after sorting by amount. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine four orders. Each has a store, a city, and an amount. Store A visits New York twice—perfect for showing how $push keeps duplicates.

mongosh
db.orders.insertMany([
  { store: "A", city: "New York", amount: 120 },
  { store: "A", city: "New York", amount: 40 },
  { store: "A", city: "Chicago", amount: 90 },
  { store: "B", city: "New York", amount: 75 }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps 4 documents in orders. Run find() to see them:

mongosh
db.orders.find()

Read each document like this:

Field in MongoDBMeaningExample
storeWhich store made the order"A"
cityCity for that order"New York"
amountOrder total120
Picture
Store A cities in order:
  New York, New York, Chicago

$push keeps every value — including duplicates.

How It Works

  1. Insert once. The sample command adds 4 documents to orders.
  2. MongoDB stores fields as written. Each document keeps the same field names and values you inserted.
  3. find() shows the same shape. What you inserted is what you get back—ready for $push in the next examples.

Example 2 — Push Cities per Store

Goal: for each store, list every city that appeared—including repeats.

mongosh
db.orders.aggregate([
  {
    $group: {
      _id: "$store",
      cities: { $push: "$city" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Split by store. _id: "$store" makes groups "A" and "B".
  2. Append each city. Every document contributes one array element.
  3. Duplicates stay. Store A’s New York appears twice because two orders used that city.
  4. Order follows arrival. Without a prior $sort, order matches how documents enter the group.

Example 3 — $push vs $addToSet

Same grouping, two accumulators side by side. $push keeps every city; $addToSet keeps each city once.

mongosh
db.orders.aggregate([
  {
    $group: {
      _id: "$store",
      citiesAll: { $push: "$city" },
      citiesSet: { $addToSet: "$city" }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Same group key. Both fields use _id: "$store".
  2. Push keeps every visit. Store A lists New York twice.
  3. Set drops the duplicate. citiesSet has New York once.
  4. Pick by intent. Full history → $push. Distinct report → $addToSet.

Example 4 — Push Objects After $sort

Goal: for each store, build an array of { city, amount } ordered by highest amount first. $push does not sort—so we $sort before $group.

mongosh
db.orders.aggregate([
  { $sort: { amount: -1 } },
  {
    $group: {
      _id: "$store",
      orders: {
        $push: {
          city: "$city",
          amount: "$amount"
        }
      }
    }
  },
  { $sort: { _id: 1 } }
]);

How It Works

  1. Sort first. { amount: -1 } puts larger amounts ahead.
  2. Push an object. Each element is { city, amount }, not a bare string.
  3. Order is preserved. Store A: 120, then 90, then 40.
  4. Need only the first few? Prefer $firstN after the same sort instead of pushing everything.

Edge Cases & Pitfalls

Check these before shipping a push-based report.

memory

Arrays can grow large

Every document adds an element. High-cardinality groups can hit the 16 MB BSON document limit—filter early or use $firstN.

order

Sort before $group when order matters

$push follows arrival order. Without $sort, do not assume chronological or ranked order.

arrays

Nested arrays need $unwind

Pushing an array field adds the whole array as one element. Flatten with $unwind first for scalars.

set

Do not use $push for unique lists

If duplicates are noise, use $addToSet instead of post-filtering a pushed array.

Performance Notes

ApproachCostBest for
$pushArray grows with every documentFull histories, ordered lists
$addToSetMembership check per valueDistinct lists, moderate cardinality
$firstNKeeps at most n valuesLeading N after a sort

Prefer $firstN or $addToSet when you do not need every value. Filter early with $match so fewer documents enter each group.

Key Takeaways

  • Role: append every value into an array per group.
  • Duplicates: kept; use $addToSet for unique lists.
  • Order: arrival order—add $sort when it matters.
  • Objects: push { field: "$x" } for structured arrays.

One line: $push builds a full array per group—every value, in order, duplicates included.

Frequently Asked Questions

$push appends the result of an expression to an array for each document in a $group bucket. Every value is kept—including duplicates—and the array grows as MongoDB processes documents in the group.
Inside $group as an accumulator: { allCities: { $push: "$city" } }. It is not a query filter—it runs while grouping documents.
$push keeps every value, including repeats. $addToSet skips values already in the array. Use $push for full histories; use $addToSet for distinct lists.
Yes. Values are appended in the order documents arrive at $group. Use $sort before $group when you need a specific order (for example chronological events).
$push adds the entire array as one element unless you $unwind first. To collect individual tags, $unwind before $group, then $push each scalar.
Yes. Use an object expression: { $push: { score: "$score", name: "$name" } } to build an array of embedded documents per group.

Next: $stdDevPop

Compute the population standard deviation per group.

$stdDevPop tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful