Home Articles

如何在MongoDB / Mongoose中实现upvote / downvote系统?

Asked
Viewed 1575 times
0

我是MongoDB的新手,我正在尝试实施一个upvote / downvote系统,以便用户可以在我的应用程序中对评论进行投票 .

我如何设置我的系统是用户通过按下应用程序中的upvote或downvote按钮通过AJAX发送POST请求,其中包含一个布尔“upvote”,如果为true则为upvote,如果为false则为downvote(此为代码工作,所以我没有包括它) . 一旦请求到达服务器,服务器就会检查用户投票的评论是否已包含投票 . 如果不是,则服务器向评论的“投票”数组添加投票,并递增或递减该评论的voteBalance属性 . 如果在该评论的“投票”数组中已经存在投票,那么它应该:

1)如果现有投票的upvote属性与新投票不同,则修改它,然后相应地修改voteBalance,或者

2)如果现有投票的upvote属性与新投票属性相同,则删除现有投票,然后相应地修改voteBalance

我插入新投票的代码工作正常,但我遇到的问题是,当投票已经存在时,我无法弄清楚如何使其工作 . 在下面的服务器端代码中,底部附近的else语句是我试图从上面处理案例1),但它不起作用 . 那么我怎样才能使这两种情况起作用呢?

这是我的评论架构:

var ReviewSchema = new mongoose.Schema({
  authorID: {
    type: String,
    required: true,
  },
  movieID: {
    type: Number,
    required: true,
  },
  date: {
    type: Number,
    required: true
  },
  username: {
    type: String,
    required: true
  },
  score: {
    type: Number,
    required: true
  },
  text: {
    type: String
  },
  voteBalance: {
    type: Number,
    required: true,
    default: 0
  },
  votes: [{
    voterID: {
      type: String,
      required: true,
    },
    upvote: {
      type: Boolean,
      required: true
    }
  }],
  comments: [{
    commenterID: {
      type: String,
      required: true,
    },
    text: {
      type: String,
      required: true
    },
    date: {
      type: Number,
      required: true
    }
  }]
},{collection: 'reviews'});

这是我用来在服务器上创建和更新投票的代码:

Review.findOne({_id: new ObjectID(reviewID), votes: { $elemMatch: { voterID: req.session._id }}}, function(err, review) {
      if (err) {
        console.log(err);
        res.status(500).send();
      }
      //If vote was not found (or if review was not found), create vote
      if (!review) {
        if (upvote) {
          var update = {$addToSet: {votes: {voterID: req.session._id, upvote}}, $inc : {voteBalance : 1}};
        }
        else {
          var update = {$addToSet: {votes: {voterID: req.session._id, upvote}}, $inc : {voteBalance : -1}};
        }

        Review.findOneAndUpdate({_id: new ObjectID(reviewID)}, update, function(err, review) {
          if (err) {
            console.log(err);
            return res.status(500).send();
          }
          res.status(200).send();
        });
      }
      //If vote was found, update
      else {
        if (upvote) {
          var update = {$set: { 'votes.$.upvote': upvote }, $inc : {voteBalance : 1}};
        }
        else {
          var update = {$set: { 'votes.$.upvote': upvote }, $inc : {voteBalance : -1}};
        }

        Review.findOneAndUpdate({_id: new ObjectID(reviewID), 'votes.$.voterID': req.session._id}, update, function(err) {
          if (err) {
            console.log(err);
            return res.status(500).send();
          }
          res.status(200).send();
        });
      }
    });

此外,我认识到这段代码可能没有那么高效,我也很感激这方面的任何提示 .

1 Answer

  • 1

    而不是 findOne() 然后 findOneAndUpdate() ,你最好使用 findOneAndUpdate()upsert option . 这样你在回调中就不需要额外的if语句了 .

    我还建议不要将 votes 存储为 ReviewSchema 中的数组 . 该数组可以不受限制地增长,因为任何数量的用户都可以对 Review 进行投票,这意味着审阅文档可能会变得庞大且笨拙 . 我建议使用映射集合 .

Related