Я работаю над механизмом социального ранжирования для предметов в базе данных. Я думаю, что у меня есть логика решена (в любом случае, в моей голове), и сейчас я работаю над реализацией. Я надеюсь либо на «Хорошо, это выглядит правильно», либо, если я полностью на неправильном пути, «Вы идиот, удалите». В зависимости от того, что применимо.
По сути, у меня есть несколько таблиц, настроенных следующим образом (намного проще, [...] указывает на другие столбцы, которые не показаны)
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.
Мое собственное предположение / решение проблемы заключается в том, чтобы сделать что-то вроде следующего:
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 ... что минусы перевешивают плюсы.
EDIT
Рекомендуется заменить
SELECT COUNT(id) INTO vote_sum
FROM Votes
WHERE item_id = itemId;
со следующим
SELECT vote_count INTO vote_sum
FROM Votes
WHERE item_id = itemId;
Это имеет больше смысла? Затем увеличьте поле voice_count вместо простого обновления счета?