6

If I add a property to a Mongoose schema and give it a default value, will existing documents receive these defaults when they are loaded?

Tamlyn
  • 22,122
  • 12
  • 111
  • 127

2 Answers2

13

Yes, but not if the query is lean.

For queries that return a full Mongoose document object – Thing.find({...}) – the default value will be returned whenever the property is missing, regardless of when the schema was changed. If the document is subsequently saved, the default value will be materialised in the database.

If the query is leanThing.find({...}).lean() – the query returns only what's in the database and this doesn't include any newly added defaults (unless the document has been loaded and saved, as above).

Tamlyn
  • 22,122
  • 12
  • 111
  • 127
  • 3
    How can we use lean with mongo defaults on existing documents? Eventually, I have to use (as many others do) `.lean()`. – Yagiz Aug 02 '16 at 21:53
  • 2
    Collection.aggregate({}) also doesn't enfore the default parameters. – null1941 Jun 12 '19 at 08:44
2

You can customize default to ignore the case where documents already exist.

Instead of doing default: Date.now, where existing documents when fetched will show the current date even if it's not set in the db, you could do this:

default: function() {
  if (this.isNew) {
    return Date.now();
  }
  return void 0;
}

Now, existing documents that do not have the field set in the db will not have it set when fetched.

Andrew Homeyer
  • 7,937
  • 5
  • 33
  • 26
  • bravo, so clever! – Normal Sep 03 '22 at 04:15
  • in addition to this answer, make sure you're not using arrow functions, and if you have `select: false` keep the defaults normally without having it be a function, because `isNew()` will not be in the scope of `$this` when this field is executed in case you have the `select` prop. – Normal Sep 04 '22 at 09:37