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