Как управлять функцией «нравится / не нравится» на основе AJAX? - PullRequest
1 голос
/ 20 декабря 2009

Я хотел бы добавить функцию like / dislike-upvote / downovote-type к каждому посту в скрипте форума, который я пишу (очень похоже на тот, что здесь, в SO). У меня две трудности, пытаясь понять, как это можно сделать:

1) Я не могу понять схему БД, которая бы делала это эффективно. Я мог бы использовать отдельную таблицу `likeordislike`, чтобы установить связь между пользователем и постом (xyz любит post # 123), или я могу использовать столбец типа \ 'text \' в таблице` posts`, перечисляя всех понравился (или не понравился) пост. Последнее, конечно, означает, что мне придется анализировать поле для идентификаторов пользователей, чтобы использовать его.

2) Убедитесь, что пользователю не нравится / не нравится сообщение дважды.

Это, вероятно, тривиально, но я могу только думать о способах, которые делают много вызовов mysql на процессах на стороне сервера. Спасибо.

Ответы [ 2 ]

3 голосов
/ 20 декабря 2009

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

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

2 голосов
/ 20 декабря 2009

(Подобный ответ Яну Ганчичу здесь, но я решил, что мой взгляд на рейтинг был достаточно другим ...)

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

Например:

create table users (
    userId varchar(254) not null,
    -- ...
    primary key (userId)
)
ENGINE=...;

create table posts (
    postId int(11) not null,
    title varchar(254) not null,
    content text not null,
    -- ...
    primary key (postId)
)
ENGINE=...;

create table userPostRatings (
    userId varchar(254) not null,
    postId int(11) not null,
    rating int(2) not null,
    -- ...
)
ENGINE=...;

create index userPostRatings_userId on userPostRatings(userId);
create index userPostRatings_postId on userPostRatings(postId);

Затем я бы использовал объединенный запрос (будь то в хранимой процедуре, в коде или в представлении) для получения информации о публикации, например ::

select p.postId, p.title, p.content, avg(r.rating)
from posts p
left outer join userPostRatings r on p.postId = r.postId
where p.postId = ?
group by p.postId;

(Это вернет NULL в среднем для всех сообщений, у которых еще нет оценок.)

Несмотря на то, что это соединение, из-за индексов в таблице userPostRatings оно довольно эффективно.

Если вы обнаружите, что объединение убивает вас (сайты с очень высоким уровнем параллелизма), то вы можете немного отменить нормализацию, как предложил Ян, добавив столбец среднего рейтинга к posts и обновляя его. , Вы просто изменили бы свой запрос, чтобы использовать его. Но я бы не стал начинать денормализованным, это больше кода и, возможно, преждевременная оптимизация. Ваша база данных находится там, чтобы отслеживать эту информацию; как только вы дублируете отслеживаемую информацию, вы сталкиваетесь с проблемами обслуживания и синхронизации. Это может быть оправдано в конце, но я бы не стал исходить из предположения, что моя БД не может помочь мне с этим. Внесение изменений (если вы планируете это заранее), если объединение является проблемой в вашей конкретной ситуации, не имеет большого значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...