我在使用mongoose时遇到了一些问题。我的目标是在预保存期间修改对象,例如必要时拆分标签或计算子文档持续时间的总和并在主文档中更新它。
我发现如果我加载一个模型,然后调用doc.update传递新数据,只有 `schema.pre('update', ...)` 能触发,我的中间件内对 `this` 进行的任何更改都不会被更新。我还尝试在我的更新中间件中使用 `this.set('...', ....);`,但无济于事。
似乎如果我用 `doc.save(...)` 代替,那么在 `schema.pre('save', ...)` 中对 `this` 的更改会按预期附加。除了将发布的变量扩展到我的模型属性并保存之外,我没有看到任何利用doc.update达成此目的的方法。
我的目标: - 通过 `doc.update(properties, ....)` 更新现有文档 - 使用保存期间的中间件修改文档,进行高级验证,并更新相关文档 - 在更新期间使用中间件修改文档,进行高级验证,并更新相关文档 - 可互换地使用 model.findByIdAndUpdate、model.save、model.findById->doc.update、model.findById->doc.save,并全部进入我的保存/更新中间件。
以下是一些任意示例代码:
我发现如果我加载一个模型,然后调用doc.update传递新数据,只有 `schema.pre('update', ...)` 能触发,我的中间件内对 `this` 进行的任何更改都不会被更新。我还尝试在我的更新中间件中使用 `this.set('...', ....);`,但无济于事。
似乎如果我用 `doc.save(...)` 代替,那么在 `schema.pre('save', ...)` 中对 `this` 的更改会按预期附加。除了将发布的变量扩展到我的模型属性并保存之外,我没有看到任何利用doc.update达成此目的的方法。
我的目标: - 通过 `doc.update(properties, ....)` 更新现有文档 - 使用保存期间的中间件修改文档,进行高级验证,并更新相关文档 - 在更新期间使用中间件修改文档,进行高级验证,并更新相关文档 - 可互换地使用 model.findByIdAndUpdate、model.save、model.findById->doc.update、model.findById->doc.save,并全部进入我的保存/更新中间件。
以下是一些任意示例代码:
function loadLocation(c) {
var self = this;
c.Location.findById(c.params.id, function(err, location) {
c.respondTo(function(format) {
if (err | !location) {
format.json(function() {
c.send(err ? {
code: 500,
error: err
} : {
code: 404,
error: 'Location Not Found!'
});
});
format.html(function() {
c.redirect(c.path_to.admin_locations);
});
} else {
self.location = location;
c.next();
}
});
});
}
LocationController.prototype.update = function update(c) {
var location = this.location;
this.title = 'Edit Location Details';
location.update(c.body.Location, function(err) {
c.respondTo(function(format) {
format.json(function() {
c.send(err ? {
code: 500,
error: location && location.errors || err
} : {
code: 200,
location: location.toObject()
});
});
format.html(function() {
if (err) {
c.flash('error', JSON.stringify(err));
} else {
c.flash('info', 'Location updated');
}
c.redirect(c.path_to.admin_location(location.id));
});
});
});
};
module.exports = function(compound) {
var schema = mongoose.Schema({
name: String,
address: String,
tags: [{ type: String, index: true }],
geo: {
type: {
type: String,
default:
"Point"
},
coordinates: [Number] // Longitude, Latitude
}
});
schema.index({
geo: '2dsphere'
});
var Location = mongoose.model('Location', schema);
Location.modelName = 'Location';
compound.models.Location = Location;
schema.pre('save', function(next) {
if(typeof this.tags === 'string') {
this.tags = this.tags.split(',');
}
});
};
==== * 修订样例 * ====
module.exports = function(compound) {
var schema = mongoose.Schema({
name: String,
bio: String
});
schema.pre('save', function(next) {
console.log('Saving...');
this.bio = "Tristique sed magna tortor?";
next();
});
schema.pre('update', function(next) {
console.log('Updating...');
this.bio = "Quis ac, aenean egestas?";
next();
});
var Author = mongoose.model('Author', schema);
Author.modelName = 'Author';
compound.models.Location = Author;
};
Author.findById
查找文档后,当我调用author.update(c.req.body, ...)
时,schema.pre('save', ...)
不会触发,但是schema.pre('update', ...)
会触发,而对this.name
的更改不会被应用。schema.pre('save', ...)
应该会触发,对吗?看起来author.save
会触发schema.pre('save', ...)
,并且随后进行的更改会被应用。那么解决方案是完全放弃author.update
吗? - user1363145doc.update()
只会触发被调用的方法的钩子,不会触发其他任何方法的钩子。 - aaronheckmannschema.pre('update', ...)
过程中进行的更改仍然没有被追加。这是一个错误、故意的还是我应该专门使用 doc.save 并使用某种方法来迭代我的 req.body 并合并属性? - user1363145document.update(doc, cb)
发送的是传递的文档的更新,而不是当前更改的值。这与document.save()
不同。 - aaronheckmann