似乎使用猫鼬post hook
s 而不是pre hook
s 解决了这个问题:
commentSchema.post("save", function(comment) {
Product.count({ _id: comment.product_id }, function(err, count) {
if (err || !count) comment.remove();
});
});
productSchema.post("remove", function(product) {
Comment.remove({ product_id: product._id }).exec();
});
让我们通过考虑四种可能的情况(我能想到的)来看看为什么这可以解决问题:
1) Comment gets saved before product is removed
2) Comment gets saved after product is removed but before post remove hook
3) Comment gets saved after product is removed and while post remove hook is
executing
4) Comment gets saved after product is removed and post remove hook executed
------------------------------------------------------------------------
In case 1, after the product is removed, the comment will be removed in the post
remove hook.
In case 2, same, post remove hook will remove the comment.
In case 3, the comment post save hook will successfully remove the comment.
In case 4, same as case 3, post save hook removes the comment.
但还有一个小问题:如果在产品被移除之后但在使用之前发生了不好的事情怎么办?post remove hook
被执行?比如说停电或者类似的事情。在这种情况下,我们最终会得到引用不存在的产品的评论。为了解决这个问题,我们可以保留pre remove hook
在产品上。这保证了只有当所有相关注释都被删除时,产品才会被删除。然而,正如OP所指出的,这并不能解决并发问题,这就是我们的地方post remove hook
来救援!所以我们需要两者:
productSchema.pre("remove", function(next) {
var product = this;
Comment.remove({ product_id: product._id }, next);
});
productSchema.post("remove", function(product) {
Comment.remove({ product_id: product._id }).exec();
});
我希望就是这样,但我仍然可以想到一个非常遥远的情况:如果在产品被删除后保存评论并且post remove hook
但在评论之前执行post save hook
执行(这将删除注释)灯熄灭!我们最终得到的评论涉及的是不存在的产品!这种情况发生的几率非常低,但仍然......
如果有人能想到一种更好的方法来处理并发,请改进我的答案或编写自己的答案!