0Pricing
MongoDB Academy · Lektion

$addFields, $replaceRoot und $mergeObjects

Sie fügen berechnete Felder hinzu, heben verschachtelte Unterdokumente auf die Root-Ebene und führen Objekte innerhalb der Pipeline zusammen.

$addFields, $replaceRoot und $mergeObjects 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.

Three Reshaping Stages

While $project is the primary document-reshaping tool, three additional stages offer more targeted transformations: $addFields adds new fields while preserving all existing ones, $replaceRoot promotes a sub-document to become the new root document, and $mergeObjects merges multiple objects into one. Together they cover reshaping patterns that would be verbose or impossible with $project alone.

$addFields: Adding Without Dropping

$addFields (also available as its alias $set) passes through all existing document fields and adds or overwrites only the specified fields. This is the key difference from $project in inclusion mode, where you must explicitly list every field you want to keep. Use $addFields whenever you want to enrich a document with computed fields without listing every existing field.

// $addFields preserves all existing fields
db.products.aggregate([{
  $addFields: {
    // Add computed fields; all original fields (name, price, etc.) are kept
    totalWithTax: { $multiply: ['$price', 1.1] },
    priceLabel: { $concat: ['$', { $toString: '$price' }] },
    isExpensive: { $gt: ['$price', 1000] }
  }
}]);
// All original product fields PLUS the three new computed fields

$set: The Modern Alias for $addFields

MongoDB 4.2 introduced $set as an alias for $addFields in both aggregation pipelines and update operations. The two are completely interchangeable in pipeline context. $set is the preferred modern spelling because it is more intuitive and mirrors the $set update operator used in updateOne(). Use whichever you find more readable.

// $set (modern) and $addFields (classic) are identical
db.orders.aggregate([{
  $set: {  // same as $addFields
    totalWithShipping: { $add: ['$amount', '$shippingFee'] },
    daysToDeliver: {
      $divide: [
        { $subtract: ['$deliveredAt', '$createdAt'] },
        1000 * 60 * 60 * 24
      ]
    }
  }
}]);

Overwriting Existing Fields With $addFields

When you specify a field name that already exists in the document, $addFields overwrites the existing value with the new computed value. This is useful for normalising data—for example, converting a string field to lowercase in the pipeline output without modifying the stored document.

// Normalise email to lowercase in pipeline output
db.users.aggregate([{
  $addFields: {
    email: { $toLower: '$email' }  // overwrites existing email field
  }
}]);
// The stored document is unchanged; only the pipeline output is normalised

// Promote a nested field to the top level by overwriting
db.orders.aggregate([{
  $addFields: {
    city: '$shippingAddress.city'  // copy nested field to top level
  }
}]);

$replaceRoot: Making a Sub-Document the Root

$replaceRoot replaces the entire root document with a specified sub-document or expression. The new root must be an object. This is useful after a $lookup + $unwind when you want the joined document to be the primary shape, or when you want to surface a nested sub-document as the output document while discarding the parent fields.

// Document: { order: { id: 1, amount: 100, customer: { name: 'Alice' } } }

// Make the nested 'order' sub-document the new root
db.transactions.aggregate([{
  $replaceRoot: { newRoot: '$order' }
}]);
// Output: { id: 1, amount: 100, customer: { name: 'Alice' } }
// The outer 'order' wrapper is gone; order's fields are now at the root level

$replaceWith: Alias for $replaceRoot

MongoDB 4.2 introduced $replaceWith as a more concise alias for $replaceRoot. Instead of { $replaceRoot: { newRoot: expr } }, you can write { $replaceWith: expr }. The two are completely equivalent. $replaceWith is often used after $lookup/$unwind to surface the joined document as the primary result.

// After lookup + unwind, make the joined product the root
db.orders.aggregate([
  { $lookup: { from: 'products', localField: 'productId', foreignField: '_id', as: 'product' } },
  { $unwind: '$product' },
  // Promote product to root, but keep orderId
  { $replaceWith: {
    $mergeObjects: ['$product', { orderId: '$_id', orderAmount: '$amount' }]
  }}
]);

$mergeObjects: Combining Two Objects

$mergeObjects merges multiple objects into a single object. When two objects have the same field, the last one wins. It is commonly used inside $replaceWith or $addFields to flatten a joined document and add extra fields at the same time. $mergeObjects can accept an array of objects or be used as a $group accumulator.

// Merge two objects - last key wins on conflict
db.users.aggregate([{
  $replaceWith: {
    $mergeObjects: [
      { defaultRole: 'viewer', isActive: false },  // defaults first
      '$$ROOT',                                     // actual doc overrides defaults
      { processedAt: '$$NOW' }                      // add computed field last
    ]
  }
}]);

$mergeObjects as a $group Accumulator

When used as a $group accumulator, $mergeObjects merges all documents in a group into a single object. This is useful for combining multiple partial documents that together form a complete record—for example, gathering all update events for an entity and merging them into a single 'current state' document.

// Merge all update events per entity into one current state
db.events.aggregate([
  { $sort: { timestamp: 1 } },  // process oldest first
  { $group: {
    _id: '$entityId',
    // Merge all event deltas into one object; later events override earlier
    currentState: { $mergeObjects: '$delta' }
  }}
]);
// Each group's 'delta' objects are merged sequentially, last wins

Practical Pattern: Flatten $lookup Result

A very common pattern is to use $replaceWith + $mergeObjects to flatten a looked-up document into the parent document's root, adding the parent's relevant fields alongside the joined document's fields. This produces a clean, flat output object that's easy to serialise and send to the client.

// Flatten order + product into a single output document
db.orders.aggregate([
  { $lookup: {
    from: 'products',
    localField: 'productId',
    foreignField: '_id',
    as: 'product'
  }},
  { $unwind: '$product' },
  { $replaceWith: {
    $mergeObjects: [
      '$product',                            // all product fields at root
      { orderId: '$_id', qty: '$qty', total: { $multiply: ['$product.price', '$qty'] } }
    ]
  }}
]);
// Clean flat output: { name, category, price, orderId, qty, total }

$unset: Removing Fields

$unset (available since MongoDB 4.2) removes specific fields from documents in the pipeline. It's the inverse of $addFields: while $addFields adds fields without touching others, $unset removes specified fields while passing through everything else. This is cleaner than using $project with all fields set to 1 just to exclude one field.

// Remove sensitive fields from output
db.users.aggregate([{
  $unset: ['password', 'apiKey', '__v']  // array of field names to remove
}]);
// All fields except password, apiKey, and __v are passed through

// Remove a single field
db.orders.aggregate([{ $unset: 'internalNotes' }]);

// Remove nested field with dot notation
db.users.aggregate([{ $unset: 'profile.ssn' }]);

Combining $addFields, $replaceRoot, and $mergeObjects

These three stages work together in sophisticated reshaping pipelines. A typical sequence is: use $addFields to compute derived fields, use $lookup to join related data, use $unwind to flatten the join, then use $replaceWith + $mergeObjects to produce a clean output shape. This combination covers most API response shaping needs without application-side transformation.

db.invoices.aggregate([
  { $addFields: { taxAmount: { $multiply: ['$subtotal', 0.08] } } },
  { $lookup: { from: 'clients', localField: 'clientId', foreignField: '_id', as: 'client' } },
  { $unwind: '$client' },
  { $replaceWith: {
    $mergeObjects: [
      { invoiceId: '$_id', subtotal: '$subtotal', taxAmount: '$taxAmount' },
      { clientName: '$client.name', clientEmail: '$client.email' }
    ]
  }},
  { $unset: ['_id'] }
]);

Quick Check

Test your understanding of $addFields, $replaceRoot, and $mergeObjects.

Lesson Recap

In this lesson you learned: $addFields/$set adds fields while preserving all existing ones, $replaceRoot/$replaceWith promotes a sub-document to the root, and $mergeObjects combines multiple objects with last-key-wins semantics. Next up we explore $out and $merge for writing pipeline results to collections.

Häufig gestellte Fragen

Ist die Lektion „$addFields, $replaceRoot und $mergeObjects“ kostenlos?

Ja — der vollständige Text von „$addFields, $replaceRoot und $mergeObjects“ 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 „$addFields, $replaceRoot und $mergeObjects“?

Sie fügen berechnete Felder hinzu, heben verschachtelte Unterdokumente auf die Root-Ebene und führen Objekte innerhalb der Pipeline zusammen. 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 „$addFields, $replaceRoot und $mergeObjects“?

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. $lookup: Collections in der Pipeline verknüpfen
  2. $unwind: Array-Felder auflösen
  3. $addFields, $replaceRoot und $mergeObjects
  4. $out und $merge: Pipeline-Ergebnisse schreiben
← Zurück zu MongoDB Academy