假设我们有一个简单的应用程序,用户可以在其中创建产品并对其进行评论。产品和注释的架构可以是:
var productSchema = new mongoose.Schema({
author_id: ObjectId,
description: String
});
var commentSchema = new mongoose.Schema({
product_id: ObjectId,
author_id: ObjectId,
message: String
});
Run Code Online (Sandbox Code Playgroud)
我们要确保每个评论都引用现有产品。这可以通过猫鼬预保存钩子轻松实现:
commentSchema.pre("save", function(next) {
Product.count({ _id: this.product_id }, function(err, count) {
if (err || !count) {
next(new Error("Could not find product"));
} else {
next();
}
});
});
Run Code Online (Sandbox Code Playgroud)
另外,如果用户删除了某个产品,我们也希望删除该产品上的所有评论。这可以通过使用预移除钩子轻松实现:
productSchema.pre("remove", function(next) {
Comment.remove({ product_id: this._id }, next);
});
Run Code Online (Sandbox Code Playgroud)
但是,如果用户A删除产品并且用户B同时对该产品发表评论,该怎么办?
可能发生以下情况:
Call pre save hook for new comment, and check if product exists
Call pre remove hook for …Run Code Online (Sandbox Code Playgroud) 因此,我正在 Node 中构建一个类似博客的小型项目,并且遇到了孤立数据库引用的问题。我在相互引用的单独文件中有两个模型。
这是我的模型:
// ./models/user
Var UserSchema = mongoose.Schema({
name: String,
posts: [{type: mongoose.SchemaTypes.ObjectId, ref:'Post'}]
});
// ./models/post
var PostSchema = mongoose.Schema({
title:String,
post_body: String,
posted_by: mongoose.SchemaTypes.ObjectId
});
Run Code Online (Sandbox Code Playgroud)
我的问题是当你删除一个帖子时,你会如何删除用户帖子数组中的引用?我的想法是我可以创建一个中间件在删除路由之前运行并在我实际删除帖子之前删除用户帖子数组中的引用。这会被认为是最好的方法吗?我在 Stack 上找到了一篇文章,它在架构中使用了“pre”函数,如下所示:
// ./models/post
PostSchema.pre('remove', function(next){
this.model('User').remove({posts: this._id}, next);
});
Run Code Online (Sandbox Code Playgroud)
这是实际的堆栈帖子:在 MongoDB 中删除时自动删除引用对象。我无法得到这项工作。但是,我确实实现了一个自定义中间件来删除引用,但觉得这可能不是最佳实践。任何提示/建议将不胜感激。谢谢!
猫鼬的文档说:
Schema.prototype.pre():
参数:
«String|RegExp» 方法名称或正则表达式匹配方法名称
[options] «Object»
[options.document] «Boolean» 如果名称是文档和查询中间件的挂钩, 设置为 true 以在文档中间件上运行。
[options.query] «Boolean» 如果 name 是文档和查询中间件的挂钩,则设置为 true 以在查询中间件上运行。
回调«函数»
还有关于预钩子“deleteOne”:
猫鼬 - 中间件
以下文档功能支持文档中间件。在文档中间件函数中,这指的是文档:
...deleteOne以下模型和查询函数支持查询中间件。在查询中间件 > 函数中,这指的是查询:
...deleteOne
所以,deleteOne 在 Document 和 Query 钩子中,现在让我们尝试使用它:
mySchema.pre('deleteOne', { document: true }, function(next) {
console.log(this)
next()
})
Run Code Online (Sandbox Code Playgroud)
结果:这是指查询,而不是文档。为什么?