Система голосования в стиле Reddit, как избежать дублирования голосов?

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

Теперь то, что я не понимаю: как мне избежать того, что пользователь будет голосовать более одного раза? Конечно, они могут просто обновить и проголосовать снова. Я читал некоторые статьи, в которых хранятся файлы cookie и т. д., но нельзя ли просто отключить файлы cookie или очистить их и снова проголосовать?

Я думал, что вам придется хранить тех, кто проголосовал, или, скорее, идентификатор того, кто проголосовал. Тем не менее, я не могу представить, как я буду это делать? Буду ли я хранить идентификатор избирателя в сообщении, за которое он голосует, или что-то еще?


person metro-man    schedule 23.04.2015    source источник
comment
Проверьте в базе данных, проголосовал ли пользователь за этот пост.   -  person Daan    schedule 23.04.2015
comment
Ну, это то, что я планировал, но как мне сохранить, если пользователь уже проголосовал за сообщение (вот в чем вопрос)   -  person metro-man    schedule 23.04.2015
comment
Целеустремленный пользователь — даже проверенный по адресу электронной почты — может проголосовать несколько раз, если захочет. Вы можете потребовать SMS-подтверждение, которое сложнее (но не невозможно) обойти, но вы можете отпугнуть реальных пользователей, которые не доверяют вам свой номер телефона.   -  person halfer    schedule 23.04.2015


Ответы (3)


Вам понадобится дополнительная таблица posts_vote или что-то в этом роде. Поместите в него поля user_id и post_id. Если пользователь голосует за публикацию, вы вставляете оба идентификатора в эту таблицу. Если пользователь проголосовал против, найдите запись и удалите ее.

person chris---    schedule 23.04.2015
comment
Отмена отрицательного голоса потребует удаления записи, но для другого (настоящего отрицательного голоса) предположительно потребуется запись для этого. - person halfer; 23.04.2015
comment
Это имеет гораздо больше смысла, я попробую. Спасибо! - person metro-man; 23.04.2015
comment
@halfer Да, я бы просто проверил, проголосовал ли пользователь за сообщение, и удалил запись о голосовании, если да? - person metro-man; 23.04.2015
comment
@metro-man: если вам нужна система в стиле Reddit, вам нужна запись для +1 или -1, а не запись для 0 (т. е. без голосования, либо потому, что пользователь не проголосовал за сообщение, либо они проголосовали и потом отменил). - person halfer; 23.04.2015
comment
В этом случае я бы использовал другое поле в той же таблице, указывающее тип голосования. Храните в нем 1 или -1. Также значительно упростит расчеты. - person chris---; 23.04.2015

Вы можете хранить записи голосования в отдельной таблице.

История голосования (вариант 1)

  • ID_избирателя
  • post_id
  • действие (голос за/против)
  • создано в

История голосования (Вариант 2)

  • ID_избирателя
  • post_id
  • баллы (в этом поле могут быть отрицательные числа для понижения)
  • создано в

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

В будущем таблица истории голосования будет расти и вызовет проблемы с производительностью, вы можете синхронизировать записи истории с помощью redis/memcached/etc. и выполняйте проверки быстрее с этими технологиями хранения.

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

Таким образом, у вас может быть два слоя для проверки того, проголосовал ли пользователь.

  1. Файлы cookie и javascript
  2. Сохраняемые данные на стороне сервера

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

person Ugur    schedule 23.04.2015

Просто в качестве примера: допустим, у вас есть таблицы posts и votes. Тогда у вас может быть posts_votes в качестве таблицы поиска.

Визуально: введите здесь описание изображения

person Markus T.    schedule 23.04.2015