Home > Back-end >  Replace field with MongoDB aggregate. Why $set, $addFields and $project, doesn't always replace
Replace field with MongoDB aggregate. Why $set, $addFields and $project, doesn't always replace

Time:04-13

Passing an object to an existing field in $set or $addFields merges objects rather than replaces them, e.g.

https://mongoplayground.net/p/aXe-rExjCXr

// Collection
[
  {
    "_id": "123",
    "options": {
      "size": "Large",
      "color": "Red"
    }
  }
]
// Aggregate
db.collection.aggregate([
  {
    $set: {
      options: {
        size: "Small"
      }
    }
  }
]);
// Expect
[
  {
    "_id": "123",
    "options": {
      "size": "Small"
    }
  }
]
// Actual
[
  {
    "_id": "123",
    "options": {
      "size": "Small",
      "color": "Red" // <-- Not expected?
    }
  }
]

(It get's even weirder with arrays)

Is it possible to have it behave like non-object values and simply replace the field?

For context, I want to use this in an aggregate update pipeline.

CodePudding user response:

This is the expected behaviour, and as far as i know there is not plan to change, as far as i remembered there was a jira with this, but they closed it, meaning that it will not change i think.

$set/$addFields replace always except

  • array field and i add document => array with all members that document
  • document field and i add document => merge documents (this is your case here)

$project replace always except

  • array field and i add document => array with all members that document

You can override this "weird" behaviour especially in case of arrays, by $unset the old field first for example, and then $set

  • Related