我想向博客Web应用程序添加评论功能。我目前有一篇文章,或者我称之为“采访”模式,如下所示:
var InterviewSchema = new mongoose.Schema({
slug: {type: String, lowercase: true, unique:true},
title: String,
description: String,
body: String,
favoritesCount: {type: Number, default: 0},
tagList: [{type: String}],
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
comments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}]
}, {timestamps: true, usePushEach: true});
它包含一个注释数组,这些注释引用了我创建的注释模型:
var CommentSchema = new mongoose.Schema({
body: String,
author: {type: mongoose.Schema.Types.ObjectId, ref:'User'},
interview: {type: mongoose.Schema.Types.ObjectId, ref:'Interview'}
}, {timestamps: true});
在路由器中,我有一个post方法可以对特定文章发表评论:
router.post('/:interview/comments', auth.required, function(req, res, next){
User.findById(req.payload.id).then(function(user) {
if(!user) {return res.sendStatus(401); }
var comment = new Comment(req.body.comment);
comment.interview = req.interview;
comment.author = user;
return comment.save().then(function() {
req.interview.comments.push(comment);
return req.interview.save().then(function(article) {
res.json({comment: comment.toJSONFor(user)});
});
});
}).catch(next);
});
当我向邮递员发送此端点请求时,收到以下错误消息:
{
"errors": {
"message": "Cannot read property 'push' of undefined",
"error": {}
}
}
在我的post方法中引用以下行:
req.interview.comments.push(comment);
我似乎无法弄清楚为什么收到此错误消息。任何建议或反馈表示赞赏!
答案 0 :(得分:1)
由于req.interview.comments
是undefined
而产生此错误。请注意,req.interview
已定义,否则您将得到无法读取未定义属性'comments'错误。
根据提供的代码,看起来您正在使用express,req.interview
很可能是使用app.param() middleware初始化的。
请尝试在代码中找到app.param('interview', function(...))
,然后仔细检查如何使用该方法解决面试。很可能是简单的Interview.findById
调用。
在这种情况下,应通过在中间件中添加以下行来解决此问题:
interview.comments = interview.comments || [];
否则,您可以修补路由处理程序:
interview.comments = interview.comments || [];
req.interview.comments.push(comment);
这应该可以解决您的问题。
中间件极有可能不是注入猫鼬模型实例,而是注入其他东西,在这种情况下,您将通过从db获取模型来解决问题:
Interview.findById(req.params.interview);
请注意,req.params用于获取采访ID。
interview.comments
设置为undefined
。像这样初始化面试模型时:
new Interview({ author: user, title: 'Demo Interview' }).save()
猫鼬将为注释属性创建并保留一个空数组。因此,可以使用显式设置为comments
的{{1}}来初始化和持久化代码访问中的某个地方,或者正在修改数据库对象。
再三考虑,此错误的根本原因很可能是由于缺少数据库迁移。
我想向博客Web应用程序添加评论功能。
更改模型架构时,猫鼬不会自动修补现有的数据库集合。因此,在您将undefined
属性引入comments
模型之后,猫鼬会使用已初始化的interview
属性来保留所有新的采访。
但是当您访问在此更改之前创建的采访时,comments
属性将丢失,从而导致此特定错误。
因此,另一种解决方案是迁移现有的db数据,例如:
comments
这样,您的所有数据将保持一致。尽管有some tools个可用于编写迁移的文件,但对于这种特定情况,它们可能会有些过分。
答案 1 :(得分:0)
首先,您得到的错误是因为req.interview.comments
未定义。您期望它是一个数组吗?
这里的问题是,您在哪里定义req.interview.comments?根据您向我显示的请求,请求中实际上应该只定义了两件事:req.params.interview
(这是采访的ID)和req.body.comment
。长话短说,req.interview.comments
是不确定的。
要解决此问题,您首先需要使用在请求参数中获得的采访ID从数据库中查找采访文档。一旦找到,就可以继续...
router.post('/:interview/comments', auth.required, function(req, res, next){
User.findById(req.payload.id).then(function(user) {
if(!user) {return res.sendStatus(401); }
return Interview.find({ _id: req.params.interview });
})
.then(function(interview) {
var comment = new Comment(req.body.comment);
comment.interview = req.params.interview;
comment.author = user;
return comment.save().then(function() {
// We are using the interview found from DB
interview.comments.push(comment);
return interview.save().then(function(article) {
res.json({comment: comment.toJSONFor(user)});
});
});
}).catch(next);
});
我稍微修改了您的代码。并非100%肯定它是准确的,但我相信您会明白。希望这会有所帮助!