Система Нравится/Не нравится с NodeJS

(Пожалуйста, найдите мое решение в моем сообщении с ответом ниже)

надеюсь, у тебя все хорошо. Мой вопрос сегодня о том, как нравится/не нравится простая система с nodeJs, и данные находятся в MongoDB.

Какова ваша ситуация?

  1. Мне дали реализацию серверной части API. Фронтенд уже сделан и его не трогать.

  2. Цель API — позволить людям публиковать острые соусы с выбором параметров. Каждый пользователь должен войти в систему для выполнения любого действия! На этом этапе разработки любое обновление, выполненное на любой странице, отправляет пользователя обратно на страницу входа.

  3. Я нахожусь в самой последней задаче, которую мне нужно выполнить, а именно: реализовать маршрут для простой системы «нравится / не нравится». Эта система имеет следующие настройки:

  • если пользователь нажимает «большой палец вверх», внешний интерфейс отправляет числовое значение «1» (далее называемое «likeStatus»)

  • если пользователь нажимает «большой палец вниз», внешний интерфейс отправляет «-1», например, статус

  • если пользователь отменяет щелчок по понравившемуся/не нравится, интерфейс отправляет «0» likeStatus

  • когда пользователь нажимает на любую кнопку, идентификатор пользователя сохраняется в одном из двух массивов, встроенных в объектную модель: usersLiked или usersDisliked в зависимости от выбора, сделанного пользователем. Обратите внимание, что оба массива включены в модель «соус», поэтому их нельзя найти в пользовательской модели.

  • на стороне интерфейса, когда пользователь нажимает на любой большой палец, другой становится серым, что не позволяет им щелкнуть по нему. Пользователь должен отменить первоначальный выбор, чтобы иметь возможность выбрать другой.

В чем твоя проблема?

Моя проблема в том, что я не могу отслеживать отмены кликов пользователя, когда они возвращаются с «1» или «-1» на «0 (ноль)». И это потому, что я не знаю, как проверить, где был пользователь, прежде чем он стал равным нулю. Мне важно обязательно удалить его из правильного массива и уменьшить правильный счетчик, а не оба или неправильный.

Попробовав то, что я описываю ниже, я ищу способ проверить:

  • где хранился userId, в каком массиве (userLiked или userDisliked)

или

  • какой у пользователя был последний статус лайка (1 или -1)

что вы пробовали до сих пор?

Я хотел использовать цепочку if/else как для проверки likeStatus, так и для поиска в массивах usersLiked и usersDisliked, чтобы увидеть, был ли там userId (здесь называемый «лайкер»). Если бы это было в userLiked, то я мог бы уменьшить счетчик лайков и наоборот, если бы id был в userDisliked. Но оба массива рассматриваются как «неопределенные» и поэтому не могут быть прочитаны.

Покажи нам свой код

Вот весь код похожего/непохожего маршрута, который я построил до сих пор:

exports.likeSauce = (req,res,next) =>{  
  const liker = req.body.userId;
  let likeStatus = req.body.like;
  let usersLiked = req.body.usersLiked;
  let usersDisliked = req.body.usersDisliked;
  if (likeStatus===1){
    sauce.updateOne({_id:req.params.id}, {$inc:{likes:+1},$push:{usersLiked:liker}})
      .then(()=>res.status(201).json({message:'you liked this sauce'}))
      .catch(error=>res.status(400).json({error}))
  } else if (likeStatus===-1) {
      sauce.updateOne({_id:req.params.id}, {$inc:{dislikes:+1},$pull:{usersLiked:liker},$push:{usersDisliked:liker}})
      .then(()=>res.status(201).json({message:'you disliked this sauce'}))
      .catch(error=>res.status(400).json({error}))
  } else if (likeStatus===0){
    if (usersLiked.includes(liker)){
      sauce.updateOne({_id: req.params.id}, { $inc: { likes: -1}, $pull: { usersLiked:liker}})
    } else if (usersDisliked.includes(liker)){
      sauce.updateOne({_id: req.params.id}, { $inc: { dislikes: -1}, $pull: { usersDisliked:liker}})
    }
  }
}

Что-нибудь еще, что может быть полезно?

вот модель "соуса" с обоими массивами в конце:

const mongoose = require('mongoose');
const sauceSchema = mongoose.Schema({
  userId: {type:String},
  name: {type:String, required:true},
  manufacturer:{type:String, required:true},
  description:{type:String, required:true},
  mainPepper: {type:String, required:true},
  imageUrl:{type:String, required:true},
  heat: {type:Number, required:true},
  likes: {type:Number},
  dislikes : {type:Number},
  usersLiked : {type:["String <userId>"]},
  usersDisliked: {type:["String <userId>"]},
});

module.exports = mongoose.model('sauce', sauceSchema);

этот вопрос перекликается с этим, но предоставленное там решение мне не очень помогло (кстати, та же ситуация)

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

Почему в вашем маршруте likeSauce запрос не отправляет вам соус, чей статус лайка изменяется? Я не понимаю, как можно поступать правильно, не зная, какой соус нравится?

jfriend00 01.12.2022 18:50

И почему в запросе идут req.body.usersLiked и req.body.usersDisliked? Есть ли какое-то промежуточное ПО, которое устанавливает те. Они, конечно, не должны исходить от клиента. Можете ли вы ТОЧНО показать, какие данные поступают от клиента?

jfriend00 01.12.2022 18:51

Этот код также выглядит так, как будто он может быть уязвим для условий гонки, потому что у вас есть массив данных из базы данных, находящихся в памяти во время асинхронной операции (что дает другим запросам возможность запускаться и конфликтовать с вашими намерениями или перезаписывать их).

jfriend00 01.12.2022 18:55

Привет @jfriend00, спасибо за ваши комментарии, но мне немного неловко отвечать вам. Во-первых, мы уже находимся на странице определенного соуса, поэтому маршрут просто выбирает идентификатор соуса. Во-вторых, они дали нам массивы для вставки в модель, но, я думаю, нет промежуточного программного обеспечения для их установки. Вы спрашиваете, что Клиент отправляет? хорошо, console.info(req.body) возвращает объект с userId и 1, или 0, или -1. Третий момент: интересно, я проверю это.

Elradsoldier 01.12.2022 20:13

Откуда массив? Вы показываете, что это исходит от req.body, что обычно означает, что оно исходит от клиента. Если это так, то это действительно плохой дизайн. Клиент никогда не должен управлять массивом. Клиент должен отправить вам одну модификацию, которую он хочет внести в массив, и вы соответствующим образом обновите базу данных, объединив их добавочную модификацию с текущими данными из базы данных.

jfriend00 01.12.2022 20:16

@jfriend00 jfriend00, насколько я знаю, массивы были реализованы в модели, которую вы найдете в конце моей ОП, но помимо этого мой сеанс просмотра передней папки ничего не дал об этих массивах. И ничего больше сзади тоже

Elradsoldier 01.12.2022 20:19

Хорошо, теперь я вижу, что, возможно, идентификатор соуса исходит от req.params.id, который анализируется из URL-адреса. Я понимаю, что один сейчас. Вам нужно знать, откуда берутся массивы, чтобы убедиться, что это не создает плохой дизайн или ошибочную реализацию в условиях гонки.

jfriend00 01.12.2022 20:22

Я спрашиваю, откуда взялись req.body.usersLiked и req.body.usersDisliked?

jfriend00 01.12.2022 20:23

Я могу сказать вам, что эти массивы появляются только дважды во всем проекте: первый в файле модели соуса, воспроизведенном в OP, и второй в обсуждаемом здесь маршруте. Так что только в бэкенде проекта, а не во фронте, вообще нет.

Elradsoldier 01.12.2022 20:23

Ну, они не появляются волшебным образом из воздуха. Вы должны упустить что-то, что их заполняет, либо в промежуточном программном обеспечении, либо в клиенте.

jfriend00 01.12.2022 20:25

Я проверю это и вернусь, когда найду решение. еще раз спасибо за все ваши комментарии до сих пор :-)

Elradsoldier 01.12.2022 20:26

Возможно, какое-то промежуточное программное обеспечение загружает весь документ соуса, и эти поля не названы конкретно в этом коде, а назначены req.body в промежуточном программном обеспечении.

jfriend00 01.12.2022 20:26

Давайте продолжим обсуждение в чате.

Elradsoldier 01.12.2022 20:30

Я разместил резюме кода в чате, указанном выше. Думаю, именно в этом маршруте создания соуса создаются массивы?

Elradsoldier 01.12.2022 20:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
14
163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец-то я решил свою проблему и подумал, что могу поделиться ею со всеми вами. Это не очень элегантное и не идеально динамичное решение, но оно, по крайней мере, помогло мне решить мою проблему. В идеале мне бы хотелось динамически увеличивать счетчики лайков и дизлайков, применяя usersLiked и usersDislikedarray.length, но если у кого-то есть идея, буду рад. Без лишних слов, вот код:

exports.likeSauce = (req, res, next) => {  
  const liker = req.body.userId;
  let likeStatus = req.body.like;
  sauce.findOne({ _id: req.params.id })
    .then((votedSauce) => {  
      if (likeStatus === 1) {
        sauce.updateOne({ _id:req.params.id }, { $push: { usersLiked: liker }, $inc: { likes:1 }})
          .then(() => res.status(201).json({ message: 'you liked this sauce' }))
          .catch(error => res.status(400).json({ error }))
      } else if (likeStatus === -1) {
        sauce.updateOne({ _id: req.params.id }, { $inc: { dislikes: 1 }, $push: { usersDisliked: liker }})
          .then(() => res.status(201).json({ message: 'you disliked this sauce' }))
          .catch(error => res.status(400).json({ error }))
      } else if (likeStatus === 0) {
        if (votedSauce.usersLiked.includes(liker)) {
          sauce.update({ _id: req.params.id }, { $inc: { likes:  -1 }, $pull: { usersLiked: liker }})
            .then(() => res.status(201).json({ message:'you un-liked this sauce' }))
            .catch(error => res.status(400).json({ error }))
          } else if (votedSauce.usersDisliked.includes(liker)) {
            sauce.updateOne({ _id: req.params.id }, { $inc: { dislikes: -1 }, $pull: { usersDisliked: liker }})
            .then(() => res.status(201).json({ message:'you un-disliked this sauce' }))
            .catch(error => res.status(400).json({ error }))
          }
      }
    })
    .catch(error => res.status(400).json({ error }))
};

Другие вопросы по теме