Как реализовать систему upvote / downvote в MongoDB / Mongoose? - PullRequest
0 голосов
/ 05 июля 2018

Я новичок в MongoDB и пытаюсь внедрить систему повышения / понижения, чтобы пользователи могли голосовать за отзывы в моем приложении.

Как я настроил свою систему, пользователь отправляет запрос POST через AJAX, нажимая кнопку повышения или понижения в приложении, которая содержит логическое «повышение», которое является положительным, если оно истинно, и понижающее, если false (этот код работает, поэтому я его не включил). Как только запрос достигает сервера, сервер проверяет, содержит ли голосование, за которое проголосовал пользователь. Если нет, сервер добавляет голосование к массиву «голосов» рецензии и увеличивает или уменьшает атрибут voiceBalance этого рецензирования. Если в массиве «голосов» этого обзора уже есть голосование, то оно должно либо:

1) Измените его, если атрибут upvote существующего голоса отличается от нового голосования, и затем соответствующим образом измените voiceBalance, или

2) Удалите существующее голосование, если его атрибут upvote такой же, как новый, и затем соответствующим образом измените voiceBalance

Мой код для вставки нового голоса работает нормально, но проблема в том, что я не могу понять, как заставить его работать, когда голосование уже существует. В приведенном ниже серверном коде оператор 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 Ответ

0 голосов
/ 06 июля 2018

Вместо findOne(), а затем findOneAndUpdate() лучше использовать findOneAndUpdate() с опцией upsert . Таким образом, вам не понадобится лишний оператор if в обратном вызове.

Я бы также рекомендовал не хранить votes как массив в ReviewSchema. Этот массив может расти без ограничений, потому что любое число пользователей может голосовать за Review, что означает, что обзорный документ может стать огромным и громоздким. Я бы рекомендовал вместо этого использовать коллекцию карт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...