Определение непрочитанных элементов на форуме


Используя PHP и MySQL, у меня есть система форумов, которую я пытаюсь создать. Я хочу знать, как я могу настроить его так, чтобы, когда пользователь читает запись на форуме, она показывалась как прочитанная ТОЛЬКО для этого пользователя, независимо от того, на каком форуме он находится, пока кто-то другой не опубликует на ней.

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

Для списка потоков в каждом форум, есть идентификатор потока (первичный ключ), имя потока, идентификатор форума, к которому он принадлежит, NUMPOSTS, numviews, LastPostDateTime и createdatetime. Есть какая-нибудь помощь?

Author: nickf, 2009-02-05

7 answers

Может храниться в другой таблице userId, ThreadId, LastReadDateTime, когда пользователь читает этот поток.

if (LastPostDateTime > LastReadDateTime) you got an unread post.

К сожалению, у вас большие накладные расходы, при каждом чтении у вас будет запись.

 3
Author: Luis Melgratti, 2009-02-05 02:13:46

Традиционным решением является объединенная таблица что-то вроде:

CREATE TABLE topicviews (
    userid INTEGER NOT NULL,
    topicid INTEGER NOT NULL,
    lastread TIMESTAMP NOT NULL,
    PRIMARY KEY (userid, topicid),
    FOREIGN KEY (userid) REFERENCES users(id),
    FOREIGN KEY (topicid) REFERENCES topics(id)
);

С последним прочтением, обновляемым каждый раз при чтении темы. При отображении списка тем, если параметр topics.lastupdated >просмотры тем.lastread, появляются новые сообщения.

Традиционное решение - это мусор и уничтожит вашу базу данных! Не делай этого!

Первая проблема заключается в том, что запись в каждом представлении темы вскоре поставит сервер базы данных на колени в загруженном форум, особенно в таблицах MyISAM, которые имеют блокировки только на уровне таблиц. (Не используйте таблицы MyISAM, используйте InnoDB для всего, кроме полнотекстового поиска).

Вы можете немного улучшить эту ситуацию, потрудившись написать только время последнего чтения, когда в теме действительно читаются новые сообщения. Если topic.lastupdated

Вторая проблема заключается в комбинаторный взрыв. Одна строка на пользователя в каждой теме вскоре складывается: всего тысяча пользователей и тысяча тем, и у вас потенциально есть миллион строк topicview для хранения!

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

Другие, менее интенсивные подходы включают:

  • сохранение только одного времени последнего чтения на форуме
  • сохранение только одного времени последнего посещения для каждого пользователя по всему сайту, которое будет отображаться как "новое" только то, что было обновлено с момента предыдущего посещения (сеанса) пользователя
  • не хранит никакой информации о последнем прочтении вообще, но включает время последнего обновления в сам URL-адрес темы. Если браузер пользователя недавно просматривал эту тему, он запомнит URL-адрес и пометит его как посетил. Затем вы можете использовать CSS для оформления посещенных ссылок как "темы, не содержащие новых сообщений".

 8
Author: bobince, 2009-02-05 02:31:49

Общие идеи здесь верны, но они упустили из виду некоторые очевидные решения проблемы масштабируемости.

@бобинс: Вторая проблема - комбинаторный взрыв. Одна строка на пользователя в каждой теме вскоре складывается: всего тысяча пользователей и тысяча тем, и у вас потенциально есть миллион строк topicview для хранения!

Вам не нужно хранить запись в таблице "просмотры тем", если кто-то никогда не просматривал эту тему. Вы бы просто отобразили тему как наличие непрочитанных сообщений, если возвращается значение null ИЛИ время последнего чтения равно

@gortok: Существует множество способов сделать это, но каждый из них растет экспоненциально по мере того, как пользователь посещает сайт.

В этом случае вы архивируете форум после n сообщений или n недель и, когда вы блокируете, очищаете таблицу "просмотры тем".

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

Но честно? Вам, вероятно, не нужно будет беспокоиться о масштабируемости. Даже миллион строк на самом деле не так уж много.

 2
Author: Shane H, 2009-02-05 04:04:17

Нет простого способа сделать это. Существует множество способов сделать это, но каждый из них растет экспоненциально по мере того, как пользователь посещает сайт. Лучшее, что вы можете сделать и при этом сохранить производительность, - это поставить отметку времени и отметить все форумы, которые были обновлены с момента последнего посещения, как "непрочитанные".

 1
Author: George Stocker, 2009-02-05 02:07:39

Вы можете просто использовать функциональность браузера пользователя и добавить последний постид в ссылку на поток следующим образом: "thread.php?id=12&lastpost=122"

Используя a:посещенный в вашем CSS, вы можете отображать сообщения, которые пользователь уже прочитал, отличные от тех, которые он не читал.

 1
Author: middus, 2009-02-06 13:18:52

У Бобинса есть много хороших предложений. Еще несколько потенциальных оптимизаций:

Запишите новую информацию "это новая?" в memcached и в таблицу "АРХИВ" MySQL. Пакетное задание может обновить "реальную" таблицу.

Для каждого пользователя установите флажок "все прочитано до даты $" (для тех случаев, когда нажата кнопка "отметить все прочитанное").

Когда публикуется что-то новое, снимите все флаги "это было прочитано" - это уменьшает количество "флагов", и таблица может быть просто (topic_id, идентификатор пользователя) - нет временных меток.

 0
Author: Ask Bjørn Hansen, 2009-02-05 09:21:01

Используемый функционал браузера пользователя и добавьте идентификатор последнего сообщения в ссылку темы. После использования a:visited в CSS вы можете отобразить все потоки, которые не были прочитаны пользователем.

 0
Author: AVINASH KUMAR, 2017-02-06 13:30:48