1位用户可以为1个酒店/汽车旅馆/对象添加1条评论[Node.js& MongoDB的]?

时间:2017-04-17 13:27:33

标签: javascript node.js mongodb express

我正在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个月的经验。这是我的第一个项目,如果这个问题看起来很愚蠢,我很抱歉。 提前谢谢!

1 个答案:

答案 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();
          }
      });
  }  
};

希望答案可以帮到你!