#node.js #mongoose #mongoose-schema #mongoose-middleware
#node.js #мангуст #мангуста-схема #mongoose-промежуточное программное обеспечение
Вопрос:
У меня есть два похожих дерева отношений родитель-потомок в моей модели данных, и я использую промежуточное программное обеспечение 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, Blog.pre('remove'...
функциональность выполняет то, для чего она предназначена, и очищает все дочерние элементы экземпляра blog.
Вызывающий код выглядит следующим образом:
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 не является функцией. Ошибка выдается при 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);
});
});
Комментарии:
1. вы зарегистрировали, какой пост на самом деле находится в вашей модели форума?
2. Да, когда я делаю вызов для получения всех сообщений на основе идентификатора форума с помощью моего REST API, я вижу правильную связь между форумом и сообщением, и когда я регистрирую данные post, полученные к
Post.find({"forumId": ObjectId("<<forum object id>")})
тому времени, я получаю ожидаемые данные. Выдает ошибку только при вызове изpre('remove'...
функции.3. Это не то, что я спрашивал. Вы когда-нибудь делали
console.log(Post)
прямо перед строкой, где Post.find не определено?4. Понял. Только что сделал, и кажется, что Post ведет себя неправильно. При выполнении console.log (Post)
{}
Однако, когда я выполняю console.log (запись) в другом рабочем примере, я получаюfunction model(doc, fields, skipId) { if (!(this instanceof model)) { return new model(doc, fields, skipId); } Model.call(this, doc, fields, skipId); }
5. Это все еще не решает основную проблему… отношение родитель-потомок одинаково в обоих случаях, определение схемы по существу одинаково в обоих случаях, вызывающий код одинаков в обоих случаях, но в одном случае он работает, а в другом выдает ошибку.