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.
doc instanceof MyModel; // true
doc instanceof mongoose.Model; // true
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 .
doc.name = 'foo';
// Mongoose sends an `updateOne({ _id: doc._id }, { $set: { name: 'foo' } })`
// to MongoDB.
await doc.save();
If the document with the corresponding _id
is not found, Mongoose will report a DocumentNotFoundError
:
// Delete the document so Mongoose won't be able to save changes
await MyModel.deleteOne({ _id: doc._id });
doc.name = 'foo';
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 .
// Update all documents in the `mymodels` collection
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.
// Cast to number failed for value "bar" at path "age"
await Person.updateOne({}, { age: 'bar' });
// Path `age` (-1) is less than minimum allowed value (0).
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()
.
const doc = await Person.findOne({ _id });
// Sets `name` and unsets all other properties
doc.overwrite({ name: 'Jean-Luc Picard' });
The other way is to use .