Использование хранимых процедур для социального ранжирования с mysql

#php #mysql #database #database-design #stored-procedures

#php #mysql #База данных #база данных-дизайн #хранимые процедуры

Вопрос:

Я работаю над механизмом социального ранжирования элементов в базе данных. Я думаю, что я разгадал логику (в любом случае, в моей голове), и сейчас работаю над реализацией. Я надеюсь либо на «Ок, это выглядит примерно так», либо, если я совершенно не на том пути, «Ты идиот, удали». В зависимости от того, что применимо.

По сути, у меня есть несколько таблиц, настроенных следующим образом (значительно упрощено, […] указывает, что другие столбцы не показаны)

 Users
id (int, primary)
email (varchar 64)
[...]

Items
id (int, primary)
URI (varchar 128)
date (timestamp)
[...]
rank (int)

Votes
id (int, primary)
user_id
item_id
  

Теперь цель состоит в том, чтобы, когда пользователь входит в систему и «голосует» за определенный элемент, он добавлял строку в таблицу голосов, но также автоматически обновлял рейтинг элемента за кулисами, используя (я бы предположил) хранимую процедуру, основанную на алгоритме, подобном другим сайтам социального ранжирования, таким как алгоритмы сортировки reddit ‘hot’ и ‘top’.

Мое собственное предположение / решение проблемы состоит в том, чтобы сделать что-то вроде следующего:

 DELIMITER //
DROP PROCEDURE IF EXISTS updateRank//
CREATE PROCEDURE updateRank(IN itemId INT())
COMMENT 'Generates a new rank and updates the Items table'
BEGIN
   DECLARE  vote_sum,published_date INT DEFAULT 0;

   SELECT COUNT(id) INTO vote_sum,
   FROM Votes
   WHERE item_id = itemId;

   SELECT date INTO published_date
   FROM Items
   WHERE id = itemId;

   SET @o  = log(max(abs(vote_sum), 1), 10);
   SET @ts = published_date - 1307557809;
   SET @r  = round(@0   1 * @ts / 45000, 7);

   UPDATE Items
   SET rank = @r
   WHERE id = itemId;
END;
//
delimiter ;
  

Затем в моем запросе PDO добавьте следующее:

 INSERT INTO Votes (user_id,item_id) values (:userid,:itemid ) CALL updateRank(:itemid);
  

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

Мои вопросы в основном таковы: есть ли лучший способ сделать это? Мой синтаксис совсем не подходит для ланча? Можно ли это сделать за кулисами (т. Е. не вызывая процедуру в моем запросе)? И должен ли я использовать InnoDB или MyISAM в качестве основного движка? У меня есть причины хотеть использовать InnoDB для этого конкретного проекта (по крайней мере, для нескольких таблиц), однако все, что я прочитал, похоже, говорит мне никогда не использовать InnoDB … что минусы перевешивают плюсы.

Редактировать

Рекомендуется заменить

 SELECT COUNT(id) INTO vote_sum
FROM Votes
WHERE item_id = itemId;
  

С помощью следующего

 SELECT vote_count INTO vote_sum
FROM Votes
WHERE item_id = itemId;
  

Имеет ли это больше смысла? Затем увеличьте поле vote_count вместо простого обновления оценки?

Комментарии:

1. Нет необходимости включать [псевдотеги] в заголовок вашего вопроса. У нас здесь есть настоящие теги!

2. Хорошо : (я опущу голову от стыда.

Ответ №1:

Не знаю, известно ли вам об этом, но есть более простой способ,

просто добавьте оценку и количество голосов к вашему элементу-сущности,

 new vote:
Score = (Score*VoteCount NewVote) / (VoteCount   1) 
VoteCount  ;
  

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

Это более легкая работа для вашего mysql, поскольку не учитывается.

//редактировать

 items:
  ItemID
  ...
  VoteSum
  VoteCount
  VoteAvg (computed field, Sum/Count, index to sort fast for "five-stars")

Track of votes - to avoid double-votes and let user delete their vote.
votes:
  UserID (PK)
  ItemID (PK)
  Rating
  

О голосовании:

  insert into votes(...
 update item set VoceCount=VotCount 1,VoteSum=VoteSum X
  

с уважением,

//t

Комментарии:

1. Хм … то есть, по сути, когда кто-то «голосует», увеличивайте столбец voteCount, если кто-то «отменяет голосование» или удаляет свой голос, уменьшайте столбец? ie: добавьте новый столбец в таблицу «Элементы» под названием «vote_count». и заменить «ВЫБРАТЬ количество голосов (id)» на «ВЫБРАТЬ количество голосов ИЗ …» в первом разделе моей процедуры?

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