Documents vs Models

and Model are distinct classes in Mongoose. The Model class is a subclass of the Document class. When you use the , you create a new document.

In Mongoose, a “document” generally means an instance of a model. You should not have to create an instance of the Document class without going through a model.

When you load documents from MongoDB using model functions like findOne(), you get a Mongoose document back.

  1. doc instanceof MyModel; // true
  2. doc instanceof mongoose.Model; // true
  3. doc instanceof mongoose.Document; // true

Updating Using save()

Mongoose documents track changes. You can modify a document using vanilla JavaScript assignments and Mongoose will convert it into .

  1. doc.name = 'foo';
  2. // Mongoose sends an `updateOne({ _id: doc._id }, { $set: { name: 'foo' } })`
  3. // to MongoDB.
  4. await doc.save();

If the document with the corresponding _id is not found, Mongoose will report a DocumentNotFoundError:

  1. // Delete the document so Mongoose won't be able to save changes
  2. await MyModel.deleteOne({ _id: doc._id });
  3. doc.name = 'foo';
  4. await doc.save(); // Throws DocumentNotFoundError

The save() function is generally the right way to update a document with Mongoose. With save(), you get full and middleware.

For cases when save() isn’t flexible enough, Mongoose lets you create your own with casting, middleware, and .

  1. // Update all documents in the `mymodels` collection
  2. await MyModel.updateMany({}, { $set: { name: 'foo' } });

Note that update(), updateMany(), findOneAndUpdate(), etc. do not execute save() middleware. If you need save middleware and full validation, first query for the document and then save() it.

Mongoose also supports limited validation on updates using the runValidators option. Mongoose casts parameters to query functions like findOne(), updateOne() by default. However, Mongoose does not run validation on query function parameters by default. You need to set runValidators: true for Mongoose to validate.

  1. // Cast to number failed for value "bar" at path "age"
  2. await Person.updateOne({}, { age: 'bar' });
  3. // Path `age` (-1) is less than minimum allowed value (0).
  4. await Person.updateOne({}, { age: -1 }, { runValidators: true });

Read the guide for more details.

There are 2 different ways to overwrite a document (replacing all keys in the document). One way is to use the Document#overwrite() function followed by save().

  1. const doc = await Person.findOne({ _id });
  2. // Sets `name` and unsets all other properties
  3. doc.overwrite({ name: 'Jean-Luc Picard' });

The other way is to use .