Example document Schema:
var CompanySchema = Schema({
created: { type: Date, default: Date.now },
modified: { type: Date, default: Date.now },
address: { type: String, required:true },
name: { type: String, required:true }
});
I'm using a common request handler for edit and create of "Company" documents:
exports.upsert = function(req, res) {
helper.sanitizeObject(req.body);
var company = {
name: req.body.name,
address: req.body.address
};
var id = req.body.id || new mongoose.Types.ObjectId();
var queryOptions = {
upsert: true
};
Company.findByIdAndUpdate(id, company, queryOptions).exec(function(error, result) {
if(!error) {
helper.respondWithData(req, res, {
data: result.toJSON()
});
} else {
helper.respondWithError(req, res, helper.getORMError(error));
}
});
};
But using this method, when a new document is inserted, created
, modified
properties are not saved with default values of Date.now
. Now I can call Company.create
depending on the existence of an id but I'm wondering why upsert does not use default values if a property does not exist on a new document?
I'm using Mongoose version ~3.8.10,
As mentioned by user whoami, mongoose only sets defaults on insert. If you are using mongoose 4. x and up and MongoDB 2.4. 0 and up you can opt-in to setting default values on update too.
The setDefaultsOnInsert Option Mongoose also sets defaults on update() and findOneAndUpdate() when the upsert option is set by adding your schema's defaults to a MongoDB $setOnInsert operator. You can disable this behavior by setting the setDefaultsOnInsert option to false .
May 20, 2019. In MongoDB, an upsert means an update that inserts a new document if no document matches the filter . To upsert a document in Mongoose, you should set the upsert option to the Model.
Mongoose save with an existing document will not override the same object reference. Bookmark this question.
What's going on is that none of Mongoose's validation, middleware, or default values are used when calling any of the "update" family of methods, like findByIdAndUpdate
. They're only invoked by calls to save
or create
.
The reason for this is that the "update" calls are effectively pass-throughs to the native driver, with Mongoose only providing type-casting of the fields based on the schema definition.
Mongoose 4.0 Update
Mongoose now supports setting defaults when a new document is created during an update
, findOneAndUpdate
, or findByIdAndUpdate
upsert. Set the setDefaultsOnInsert
option to true
to enable this. This uses the $setOnInsert
operator to create the defaults on insert.
var queryOptions = { upsert: true, setDefaultsOnInsert: true }; Company.findByIdAndUpdate(id, company, queryOptions).exec( ...
You may use { "$setOnInsert": { value: 31 } }
Doc
Ref: https://groups.google.com/forum/#!topic/mongoose-orm/WuJSqxPX8T8
syntax: findOneAndUpdate([query], [doc], [options], [callback])
Doc
example:
model.findOneAndUpdate( { username: 'john' }, { "$setOnInsert": { points: '0' }, $push: { "boards": { "account":req.body.account, "game":req.body.game } } { upsert: true}, function(err, doc) { });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With