Mongoose.js:isModified标志为具有默认值的属性

我有一个默认生成值的模型,在整个文档生命周期中不会改变,除非在特殊情况下。

使用doc.update({_id: doc._id, deleted_at: new Date()}, {overwrite: true})将文档标记为已删除

在一个非常特殊的情况下,这个文件可能会被“复活” – 被它的id抬起头,然后再被使用。

在保存前钩子中,每当文档被创build或复活时,我都需要执行一些操作(例如将文档存储在另一个集合中)。

考虑下面的简化代码:

 'use strict'; var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/test'); var someSchema = mongoose.Schema({ immutable: { type: String, default: function () { return 'SomeVeryRandomValue'; } } }); someSchema.pre('save', function (next) { if (this.isNew || this.isModified('immutable')) { console.log('Processing pre-save hook!'); } next(); }); var SomeModel = mongoose.model('SomeModel', someSchema, 'test'); mongoose.connection.once('open', function (err) { var testDoc = new SomeModel({}); console.log('New: %j', testDoc.toObject()); testDoc.save(function(err) { console.log('Initial saved: %j', testDoc.toObject()); testDoc.update({_id: testDoc._id}, {overwrite: true}, function (err) { // at this point using mongo console: // > db.test.findOne() // { "_id" : ObjectId("5617b028bf84f0a93687cf67") } SomeModel.findById(testDoc.id, function(err, reloadedDoc) { console.log('Reloaded: %j', reloadedDoc.toObject()); console.log('reloaded isModified(\'immutable\'): %j', reloadedDoc.isModified('immutable')); reloadedDoc.save(function(err) { console.log('Re-saved: %j', reloadedDoc); mongoose.connection.close(); }); }); }); }); }); 

脚本运行时输出:

 $ node mongoose-modified-test.js New: {"_id":"5617b64c5376737b46f6bb98","immutable":"SomeVeryRandomValue"} Processing pre-save hook! Initial saved: {"__v":0,"_id":"5617b64c5376737b46f6bb98","immutable":"SomeVeryRandomValue"} Reloaded: {"_id":"5617b64c5376737b46f6bb98","immutable":"SomeVeryRandomValue"} reloaded isModified('immutable'): false Re-saved: {"_id":"5617b64c5376737b46f6bb98","immutable":"SomeVeryRandomValue"} 

immutable的不被标记为修改,恕我直言,它应该 – 原始文件没有该属性的值。

解决方法是删除immutable属性的默认值,并像这样定义预validation钩子:

 someSchema.pre('validate', function (next) { if (this.isNew || !this.immutable) { this.immutable = 'SomeVeryRandomValue'; } next(); }); 

这不是我所需要的,因为在我尝试validation/保存文档之前,不会生成这个值。 new SomeModel({})上不执行前/后的挂钩,所以我不能使用这些。

我应该为mongoose.js打开一个问题吗?

this.$isDefault('immutable')可以用来代替。

 someSchema.pre('save', function (next) { if (this.isNew || this.$isDefault('immutable')) { console.log('Processing pre-save hook!'); } next(); }); 

使用更新的预保存钩子输出脚本:

 $ node --harmony mongoose-modified-test.js New: {"_id":"56276f0c1a2f17ae7e0a03f7","immutable":"SomeVeryRandomValue"} Processing pre-save hook! Initial saved: {"__v":0,"_id":"56276f0c1a2f17ae7e0a03f7","immutable":"SomeVeryRandomValue"} Reloaded: {"_id":"56276f0c1a2f17ae7e0a03f7","immutable":"SomeVeryRandomValue"} Processing pre-save hook! Re-saved: {"_id":"56276f0c1a2f17ae7e0a03f7","immutable":"SomeVeryRandomValue"} 

感谢@ vkarpov15 澄清 。