Reputation: 942
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,
Upvotes: 23
Views: 8959
Reputation: 311935
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( ...
Upvotes: 51
Reputation: 1033
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) {
});
Upvotes: 8