0Pricing
MongoDB Academy · Lektion

Array-Update-Operatoren: $push, $pull, $addToSet

Fügen Sie mit gezielten Array-Update-Operatoren Elemente zu Arrays in Dokumenten hinzu oder entfernen Sie sie daraus.

Array-Update-Operatoren: $push, $pull, $addToSet ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des MongoDB Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.

Arrays as First-Class Citizens

Arrays inside MongoDB documents are common—a product has tags, a user has roles, an order has items. When these arrays need to change (add a tag, remove a role, append an order item), you need array update operators that modify the array in-place rather than replacing the entire document.

MongoDB provides a full set of operators for this purpose: $push adds elements, $pull removes elements by value, $pop removes from ends, and $addToSet adds only if unique. All of these are atomic—the change happens in a single server-side operation.

$push: Adding Elements to an Array

The $push operator appends one or more elements to an array field. If the field does not exist, $push creates it as a new array containing the pushed element. If the field exists but is not an array, the operation fails.

A single $push with a plain value adds one element. To add multiple elements in one operation, combine $push with the $each modifier. $push does not check for duplicates—use $addToSet if you need uniqueness.

// Push a single element
db.posts.updateOne(
  { _id: postId },
  { $push: { tags: 'mongodb' } }
);
// tags: ['node', 'backend'] -> ['node', 'backend', 'mongodb']

// Push multiple elements using $each
db.posts.updateOne(
  { _id: postId },
  { $push: { tags: { $each: ['databases', 'nosql'] } } }
);
// tags: ['node'] -> ['node', 'databases', 'nosql']

// Push a sub-document
db.users.updateOne(
  { _id: userId },
  { $push: { addresses: { street: '123 Main St', city: 'Chicago' } } }
);

$push With $sort and $slice

Combining $push with the $sort and $slice modifiers creates a capped sorted array: push new elements, sort the array, then trim it to a maximum length. This pattern is perfect for maintaining a 'top N' list or a 'recent N items' log.

The $slice modifier limits the array to the first N elements after sorting. Use negative values for last N (e.g., $slice: -5 keeps the last 5 after sort). This combination requires $each even if you are pushing a single item.

// Maintain a 'top 5 scores' list
db.players.updateOne(
  { _id: playerId },
  {
    $push: {
      topScores: {
        $each:  [{ score: 9800, date: new Date() }],
        $sort:  { score: -1 },  // Sort by score descending
        $slice: 5               // Keep only top 5
      }
    }
  }
);
// After: topScores always has max 5 entries, highest scores first

$pull: Removing Elements by Value

The $pull operator removes all elements from an array that match a specified value or condition. Unlike $pop (which removes from an end), $pull removes elements by their value anywhere in the array.

You can pass a simple value (for primitive arrays) or a query condition (for arrays of sub-documents). $pull removes all matching elements in one atomic operation—there is no need to know the position of the element.

// Remove a tag by value
db.posts.updateOne(
  { _id: postId },
  { $pull: { tags: 'outdated' } }
);
// tags: ['mongodb', 'outdated', 'nosql'] -> ['mongodb', 'nosql']
// Removes ALL occurrences of 'outdated'

// Pull with a condition on array of sub-documents
db.orders.updateOne(
  { _id: orderId },
  { $pull: { items: { sku: 'REMOVED-ITEM' } } }
);
// Removes all items where sku = 'REMOVED-ITEM' from the items array

$pop: Removing From Array Ends

The $pop operator removes the first or last element of an array without needing to know the value. Use $pop: { field: 1 } to remove the last element, and $pop: { field: -1 } to remove the first element.

$pop is useful for implementing queues and deques: push to the back with $push, pop from the front with $pop: -1. However, for production queue systems, consider dedicated solutions—document-based queues have limitations under high concurrency.

// Remove the last element
db.playlists.updateOne(
  { _id: playlistId },
  { $pop: { songs: 1 } }   // 1 = last
);
// songs: ['A', 'B', 'C'] -> ['A', 'B']

// Remove the first element
db.queues.updateOne(
  { _id: queueId },
  { $pop: { items: -1 } }  // -1 = first
);
// items: ['task1', 'task2', 'task3'] -> ['task2', 'task3']

$addToSet: Unique Element Insertion

The $addToSet operator adds an element to an array only if it is not already present. If the element already exists, the operation is a no-op—no duplicate is added. This is ideal for maintaining sets of unique values like tags, user roles, or category memberships.

Like $push, $addToSet supports the $each modifier to add multiple unique elements in one operation. If the field does not exist, it creates the array. BSON type and value must match exactly for the duplicate check.

// Add tag only if not already present
db.posts.updateOne(
  { _id: postId },
  { $addToSet: { tags: 'mongodb' } }
);
// If tags already has 'mongodb': no change
// If not: 'mongodb' is added

// Add multiple unique roles with $each
db.users.updateOne(
  { _id: userId },
  { $addToSet: { roles: { $each: ['viewer', 'commenter'] } } }
);
// Only adds roles that aren't already in the array
// 'viewer' already exists? Skipped. 'commenter' new? Added.

$push vs $addToSet: Choosing

The choice between $push and $addToSet depends on whether order and duplicates are acceptable:

  • Use $push when: order matters, duplicates are acceptable (or expected), you need sorted arrays with $sort/$slice, or you are building a log/history where repeated values make sense
  • Use $addToSet when: you are managing a set of unique values (roles, permissions, tags, subscriptions) and adding an existing value should be a no-op

Keep in mind that $addToSet must scan the existing array to check for duplicates—for very large arrays (thousands of elements), this can be slow. Consider a separate collection for large unique sets.

// $push for ordered history (duplicates ok)
db.users.updateOne(
  { _id: userId },
  { $push: { loginHistory: { at: new Date(), ip: req.ip } } }
);
// Same IP can appear multiple times - that's fine for history

// $addToSet for unique roles (no duplicates)
db.users.updateOne(
  { _id: userId },
  { $addToSet: { roles: 'editor' } }
);
// 'editor' is either added or already there - always unique

Removing Specific Elements From Nested Arrays

When your document has an array of sub-documents and you need to remove a specific sub-document by one of its fields, use $pull with a condition expression. The condition is evaluated against each array element and all matching elements are removed.

For removing multiple specific values at once from a primitive array, $pullAll is a shortcut that accepts an array of values to remove: { $pullAll: { tags: ['oldTag1', 'oldTag2'] } }. It is equivalent to { $pull: { tags: { $in: ['oldTag1', 'oldTag2'] } } }.

// Remove all items in an order for a discontinued product
db.carts.updateOne(
  { _id: cartId },
  {
    $pull: {
      items: { productId: ObjectId('discontinued-id') }
    }
  }
);

// $pullAll: remove multiple values at once
db.posts.updateOne(
  { _id: postId },
  { $pullAll: { tags: ['spam', 'outdated', 'test'] } }
);
// Removes all occurrences of 'spam', 'outdated', and 'test'

Array Length Management

Be cautious about unbounded array growth. Arrays that grow without limit (unbounded arrays) cause documents to grow beyond MongoDB's 16 MB limit and degrade performance as the array index size grows.

Strategies for bounded arrays:

  • Use $push + $slice: -N to keep only the last N elements (rolling window)
  • Set a business rule: maximum 50 items in cart, maximum 100 history entries
  • For truly unbounded collections, move to a separate collection with a reference instead of embedding
// Keep only the last 100 login history entries
db.users.updateOne(
  { _id: userId },
  {
    $push: {
      loginHistory: {
        $each: [{ at: new Date(), ip: req.ip }],
        $slice: -100   // Keep last 100 (most recent)
      }
    }
  }
);
// loginHistory never exceeds 100 entries
// Oldest entries are automatically dropped

Real-World: User Following System

Social features like 'follow user' and 'unfollow user' map naturally to $addToSet and $pull. When a user follows someone, add the followed user's ID to the follower's following array. When they unfollow, pull it out. The atomic nature of these operators means two simultaneous follow/unfollow actions on the same document will be serialized correctly.

For large social graphs (millions of followers), this embedded array approach hits the 16 MB document limit. At scale, move relationships to a dedicated follows collection with followerId and followeeId fields.

// Follow a user
async function followUser(followerId, followeeId) {
  await db.collection('users').updateOne(
    { _id: new ObjectId(followerId) },
    { $addToSet: { following: new ObjectId(followeeId) } }
  );
  // Optionally: add to followee's followers array too
}

// Unfollow a user
async function unfollowUser(followerId, followeeId) {
  await db.collection('users').updateOne(
    { _id: new ObjectId(followerId) },
    { $pull: { following: new ObjectId(followeeId) } }
  );
}

The Positional $ Operator in Updates

When you need to update a specific element within an array that matched your query, use the positional $ operator. In the update document, $ refers to the first array element that matched the filter condition.

For example, to mark a specific order item as shipped, filter by { 'items.sku': 'A1' } and then update { : { 'items.$.shipped': true } }. The $ acts as a placeholder for the index of the matched array element. If multiple elements match, only the first is updated.

// Update a specific array element using positional operator
// Find order containing item sku 'A1', mark it shipped
db.orders.updateOne(
  { _id: orderId, 'items.sku': 'A1' },   // Filter: includes array condition
  { : { 'items.$.shipped': true } }  // $: matched array element index
);
// Before: items: [{sku:'A1',shipped:false},{sku:'B2',shipped:false}]
// After:  items: [{sku:'A1',shipped:true},{sku:'B2',shipped:false}]

Quick Check

Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.

Lesson Recap

In this lesson you learned: $push appends elements to an array and supports $each/$sort/$slice modifiers for maintaining capped sorted arrays like top-N lists, $pull removes all matching elements by value or condition—use $pullAll to remove multiple specific values at once, and $addToSet adds an element only if absent—ideal for maintaining unique sets like user roles, tags, and permissions without application-level duplicate checks. Next up we explore how to safely delete documents with deleteOne and deleteMany.

Häufig gestellte Fragen

Ist die Lektion „Array-Update-Operatoren: $push, $pull, $addToSet“ kostenlos?

Ja — der vollständige Text von „Array-Update-Operatoren: $push, $pull, $addToSet“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des MongoDB Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Array-Update-Operatoren: $push, $pull, $addToSet“?

Fügen Sie mit gezielten Array-Update-Operatoren Elemente zu Arrays in Dokumenten hinzu oder entfernen Sie sie daraus. Du übst MongoDB Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um MongoDB Academy zu starten?

Keine Vorkenntnisse erforderlich. MongoDB Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Array-Update-Operatoren: $push, $pull, $addToSet“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser MongoDB Academy-Lektion Code schreiben und ausführen?

Ja. Jede MongoDB Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. updateOne und updateMany mit $set und $unset
  2. Inkrement-, Multiplikations- und Min/Max-Operatoren
  3. Array-Update-Operatoren: $push, $pull, $addToSet
  4. Dokumente sicher mit deleteOne und deleteMany löschen
← Zurück zu MongoDB Academy