我的数据模型中有两个相似的父子关系树,我正在使用 Mongoose 的中间件来处理级联删除。
第一个层次结构表示如下:
//blog.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Entry = require('./entry.js');
var Follower = require('./follower.js');
var Blog = new Schema({
author: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
name: {
type: String,
required: true
},
headerImageUrl: String,
description: {
type: String,
required: true
}
}, {
timestamps: true
});
Blog.pre('remove', function(next) {
Entry.find({"blogId": this._id})
.exec(function(err, entries) {
console.log("found entries " + entries);
for(var i = entries.length -1; i >= 0; i--) {
entries[i].remove();
}
});
Follower.remove({"blogId": this._id}).exec();
next();
});
module.exports = mongoose.model('Blog', Blog);
//entry.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Blog = require('./blog.js');
var Comment = require('./comment.js');
var Entry = new Schema({
blogId: {
type: Schema.Types.ObjectId,
ref: 'Blog'
},
title: String,
thumbnailUrl: String,
content: String
}, {
timestamps: true
});
Entry.pre('remove', function(next) {
Comment.remove({"entryId": this._id}).exec();
next();
});
module.exports = mongoose.model('Entry', Entry);
//comment.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Entry = require('./entry.js');
var Post = require('./post.js');
var Comment = new Schema({
text: {
type: String,
required: true
},
postedBy: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
parentComment: this,
entryId: {
type: Schema.Types.ObjectId,
ref: 'Entry'
},
postId: {
type: Schema.Types.ObjectId,
ref: 'Post'
},
type: {
type: String,
enum: ['BLOG', 'FORUM', 'COMMENT'],
required: true
}
}, {
timestamps: true
});
module.exports = mongoose.model('Comment', Comment);
在这种情况下,当在博客实例上调用 remove 时,该Blog.pre('remove'...
功能会执行预期的操作并清除博客实例的所有子级。调用代码如下:
blogRouter.route('/:blogId')
//delete a specific blog by blog id: [OWNER OR ADMIN USER]
.delete(Verify.verifyOrdinaryUser, Verify.verifyBlogOwnerOrAdmin, function(req, res, next) {
Blog.findById(req.params.blogId, function(err, blog) {
if(err) return next(err);
blog.remove();
res.json(blog);
});
});
我对第二个层次结构做同样的事情,在这里直观地表示:论坛层次结构和以下代码:
//forum.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Post = require('./post.js');
var Subscription = require('./subscription.js');
var Forum = new Schema({
title: {
type: String,
required: true
},
description: String,
moderators: [
{
type: Schema.Types.ObjectId,
ref: 'User'
}
]
}, {
timestamps: true
});
Forum.pre('remove', function(next) {
Post.find({"forumId": this._id})
.exec(function(err, posts) {
console.log("found posts " + posts);
for(var i = posts.length -1; i >= 0; i--) {
posts[i].remove();
}
});
Subscription.remove({"forumId": this._id}).exec();
next();
});
module.exports = mongoose.model('Forum', Forum);
//post.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.js');
var Forum = require('./forum.js');
var Comment = require('./comment.js');
var Post = new Schema({
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
postText: {
type: String,
required: true
},
forumId: {
type: Schema.Types.ObjectId,
ref: 'Forum'
},
}, {
timestamps: true
});
Post.pre('remove', function(next) {
Comment.remove({"postId": this._id}).exec();
next();
});
module.exports = mongoose.model('Post', Post);
//comment.js [SAME AS INCLUDED ABOVE]
但是在这种情况下,当在论坛实例上调用 remove 时,该Forum.pre('remove'...
功能会引发错误:TypeError: Post.find is not a function。错误在 forum.js 第 24 行(Forum.pre(...) 块中的第二行)引发
调用代码如下:
forumRouter.route('/:forumId')
//delete forum by id: [ADMIN]
.delete(Verify.verifyOrdinaryUser, Verify.verifyAdmin, function(req, res, next) {
Forum.findById(req.params.forumId, function(err, forum) {
if(err) return next(err);
forum.remove();
res.json(forum);
});
});
虽然我在这里和其他地方的在线研究中发现了这个错误的实例,但原因是错误导出的模型或错误定义的模式。Post 模式在我的其余代码中成功使用,没有任何问题,只是对 Post.find 的调用导致了错误。事实上,我的 postRouter 代码成功调用了以下代码:
postRouter.route('/')
// retrieve all forum posts: [ALL USERS]
.get(function(req, res, next) {
Post.find({})
.populate({
path: 'forumId',
model: 'Forum',
populate: {
path: 'moderators',
model: 'User'
}
})
.populate('createdBy')
.exec(function(err, posts){
if(err) return next(err);
res.json(posts);
});
});