我正在Node.js中构建一个项目(使用Express和MongoDB(使用Mongoose),登录用户可以在其中添加评论到酒店。但是我不希望用户向一个酒店添加多个评论。酒店(只能编辑或删除现有的)。
所以我决定创建一个中间件功能,它将检查登录的用户ID是否与酒店评论作者的任何ID相匹配。如果是,我将重新定向用户(当然添加用户已经向酒店添加评论的flash消息等等)。但它对我来说并不是很整洁。
在酒店的模型中,我实施了评论属性,我只存储了引用评论的ID
middleWare.noRepeat = function(req, res, next){
if(req.isAuthenticated()){
Hotel.findById(req.params.id, function(err, foundHotel){
if(err){
console.log(err);
} else{
foundHotel.reviews.forEach(function(review){
Review.findById(review, function(err, foundReview) {
if(err){
console.log(err);
} else{
if(foundReview.author.id.equals(req.user._id)){
res.redirect("back");
//flash message to be implemented
} else {
next();
}
}
});
});
}
});
}
};
此代码对我来说效果不佳。我收到错误说"无法读取null"的作者属性。我认为这部分在这里:
foundHotel.reviews.forEach(function(review){
Review.findById(review, function(err, foundReview) {
可能是个问题。我使用评论作为 findById 方法的id参数,因为在我提到的酒店模型中我有一个review属性,这是一个存储相关的数组审查的ID。它看起来像这样:
reviews: [ ObjectId("53f3ada529cb20192ra35c8h"),
ObjectId("12f3d6afdcd3cd15ktbcf8e98i"),
ObjectId("1234abcdef56ghijk")]
最后,我只是初学者,有2.5个月的经验。这是我的第一个项目,如果这个问题看起来很愚蠢,我很抱歉。 提前谢谢!
答案 0 :(得分:0)
嵌套异步调用,Hotel.findById()
& Review.findById()
,可能会导致问题。如果您是开放的,那么让我建议您使用mongoose populate的替代方法。我假设你的酒店架构看起来像这样:
{
// some properties
reviews: [Schema.Types.ObjectId]
}
您可以将酒店架构更改为如下所示:
{
// some properties
reviews: [{
type: Schema.Types.ObjectId,
ref: 'review' //refer your review schema here
}]
}
这样做的好处是:
您可以按ID和populate评论查找酒店,完全避免Review.findById()
。
所以你的中间件应该是这样的:
middleWare.noRepeat = function(req, res, next){
if(req.isAuthenticated()){
Hotel
.findById(req.params.id)
.populate('reviews')
.exec(function(err, foundHotel){
if(err){
console.log(err);
} else{
foundHotel.reviews.forEach(function(review){
// this time the review variable
// will contain complete review object,
// rather than containing only id
if(review.author.id.equals(req.user._id)){
return res.redirect("back");
//flash message to be implemented
}
});
return next();
}
});
}
};
希望答案可以帮到你!