Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Запоминание просмотренных тем форума


Автор: Gold Dragon 6.3.2013, 20:56
Подобные темы уже всплывали. Но вот в очередной раз у меня делема: Как учитывать просмотренные темы форума..?
Т.е. пока пользователя не было на форуме, кто-то отвечал. Человек заходит и видит что есть темы где без него что-то ответили.. Заходит в темы и она помечается прочитанной..

Как такое организовать и какие вообще решения на сегодня есть?

Автор: ksnk 6.3.2013, 21:18
В данных пользователя храниться список ID тем через запятую, по этому списку строится массив читаных тем. Установка флага читал-нечитал ставится после получения дерева тем, сравнением в цикле id-шек с этим массивом. В дополнение  этому есть дата, после которой все темы считаются прочитанными. Когда массив прочитанных тем становится очень большим - он сокращается в два раза, при этом дата прочитанных сдвигается  вверх.

Как-то так...  smile 

Автор: mark2011 6.3.2013, 21:41
ksnk, 
Интересно, как вы это себе представляете?

Мой вариант такой: у пользователя есть дата последнего посещения на форуме. Правильно? Когда он заходит следующий раз, делается опрос всех тем на форуме на предмет: есть ли сообщения с датой позже даты последнего посещения пользователя на форуме. Если такие сообщения есть, соответственно помечаем такие темы непрочитанными. 

Автор: Arantir 6.3.2013, 22:21
mark2011, вообще-то, если добавить в конец вашего варианта вариант ksnk, то получится именно то, что вы оба, судя по всему, и имели ввиду =)

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

Автор: ksnk 7.3.2013, 07:43
Цитата(mark2011 @  6.3.2013,  21:41 Найти цитируемый пост)
ksnk, 
Интересно, как вы это себе представляете?

У пользователя в данных хранится текстовое поле `seen_topics`/ и поле даты `past_seen_date`.

-- при выборе тем из базы выполняется что-то вроде такого запроса
 
Код

 $sql=' select topic.ID, topic.`DATE`,..., (topic.`DATE`<'.$user['past_seen_date'].' or topic.ID in ('. $user['seen_topics'].') as seen from ...';

  значение seen и будет просмотрена или нет тема. 
  Или просто весь выбранный массив проверяется отдельным циклом.

-- каждый раз, когда открывается новая, непросмотренная тема, в поле `seen_topics` добавляется ID этого топика. `seen_topics` .=','.ID ;

-- если длина (текстовая) поля `seen_topics` становится больше 4к (среднепотолочное значение) - это примерно 4к/6=600 уникальных ID, делается такой запрос 
   
Код

 $sql=' select topic.ID, topic.`DATE` from topics where topic.ID in ('. $user['seen_topics'].') order by topic.`DATE` limit 300,100000';  
(300 - это 600/2. 100000 - это заведомо бОльшее, чем количество топиков в `seen_topics`, значение) Первое значение этой выборки даст нам новое значение параметра `past_seen_date`. Все полученные таким образом ID дадут нам новое значение поля `seen_topics`.

Автор: Gold Dragon 7.3.2013, 08:00
Цитата(mark2011 @  6.3.2013,  22:41 Найти цитируемый пост)
есть ли сообщения с датой позже даты последнего посещения пользователя на форуме.

Я зашёл на форум и мне показали непрочитанные темы. При этом обновилась таблица о моём последнем посещении. Я обновляю страницу и все стемы становятся прочитанными smile

Arantir, что-то запутался... Я зашёл на сайт и должен сформироваться список непрочитанных тем. Каким образом?

ksnk, так я не понял что учитывать, прочтённые или не прочтённые  smile 

И опять же вопрос встаёт в нагрузке на БД

Автор: ksnk 7.3.2013, 08:08
Цитата(Gold Dragon @  7.3.2013,  08:00 Найти цитируемый пост)
так я не понял что учитывать, прочтённые или не прочтённые

 smile Прочтенные - проще, не нужно менять ВСЕ записи ВСЕХ юзеров с попявлением новых тем. 
К тому же, удаленные темы никак не сказываются на этой схеме.

Автор: Gold Dragon 7.3.2013, 08:10
ну  это самый простой вариант.. а теперь примени его например к этому форуму.. Сколько тут тем, сколько тут пользователей и какой объём эта таблица будет и скорость её обработки?

Автор: mark2011 7.3.2013, 08:51
Цитата(Gold Dragon @  7.3.2013,  08:00 Найти цитируемый пост)
Я обновляю страницу и все стемы становятся прочитанными

Не-а....

Тема становится прочитанной только тогда, когда ты реально вошёл в неё, т.е. затребовал страницу типа topic.php?topic_id=1. При этом таблица обновится и тема будет считаться прочтённой.

Цитата(Gold Dragon @  7.3.2013,  08:00 Найти цитируемый пост)
И опять же вопрос встаёт в нагрузке на БД 

memcached? apc? eaccelerator? mysql optimize?? ))

Автор: ksnk 7.3.2013, 09:50
Цитата(Gold Dragon @  7.3.2013,  08:10 Найти цитируемый пост)
ну  это самый простой вариант.. а теперь примени его например к этому форуму.. Сколько тут тем, сколько тут пользователей и какой объём эта таблица будет и скорость её обработки? 

Количество тем, которые юзер просмотрел - конечно. Количество тем, которые юзер не видел - несчетно  smile  

Причем тут скорость обработки? Выборка по ключевому полю довольно быстрая штука, конструкция in в запросе тоже не сильно тормозит. 
Для экономии места для хранения прочитанных тем - можно чистить темы у неактивных юзеров, оставляя им поменьше, или оставляя только `нижнюю дату`. 

А вообще - все познается на практике. Можно спросить у Wowa как оно сделано тут.

Автор: Aliance 7.3.2013, 12:05
Цитата(ksnk @  6.3.2013,  22:18 Найти цитируемый пост)
В данных пользователя храниться список ID тем через запятую

Цитата(ksnk @  7.3.2013,  08:43 Найти цитируемый пост)
У пользователя в данных хранится текстовое поле `seen_topics`

мне кажется так делать не стоит.

Автор: ksnk 7.3.2013, 12:13
Aliance, а почему? Текстовая строка используется кк запчасть в sql запросах.

Автор: Arantir 7.3.2013, 12:30
Цитата(Gold Dragon @  7.3.2013,  07:00 Найти цитируемый пост)
Я зашёл на сайт и должен сформироваться список непрочитанных тем. Каким образом?

Новые темы/сообщения гарантированно непрочитанные. Новые — созданные после последней активности пользователя.
Список не создается, а дополняется такими темами. При этом в списке хранятся еще и все прошлые непрочитанные немы.
Прочтение темы означает удаление ее из списка непрочитанных.

Автор: Gold Dragon 7.3.2013, 12:41
хоть убейте, никак не могу нащупать мыль...

В общем делаю предварительное резюмирование

Пользователь зашёл на сайт:
- считывается дата его последнего пребывания
- считываются новые сообщения ДАТА_ПОСЛЕДНЕГО_ВИЗИТА < ДАТА_СООБЩЕНИЯ
- считываем данные у пользователя по форумам
- синхронизируем: добавляем недостающие id форумов
- изменяем дату последнего пребывания

Пользователь заходит на форум:
- считывается дата его последнего пребывания
- считываются новые сообщения ДАТА_ПОСЛЕДНЕГО_ВИЗИТА < ДАТА_СООБЩЕНИЯ
- считываем данные у пользователя по форумам
- синхронизируем: добавляем недостающие id форумов + удаляется форум в который зашёл
- изменяем дату последнего пребывания

Так?


Автор: Arantir 7.3.2013, 12:59
Не думаю, что надо обновлять весь список при посещении каждого форума. Весь обновлять только на главной странице, а для каждого форума/раздела дополнительно проверять индивидуально, просто добавив условие с ID раздела в запрос. Ведь вдруг пользователь вообще интересуется лишь одним разделом и в другие даже не ходит. 

Автор: Gold Dragon 7.3.2013, 13:21
т.е.  обновлять нужно будет если я посещаю не форум, а просматриваю раздел/категорию/главную... так? А при посещении конкретной темы, только удалять... так?

Автор: Aliance 7.3.2013, 13:24
Цитата(ksnk @  7.3.2013,  13:13 Найти цитируемый пост)
Aliance, а почему? Текстовая строка используется кк запчасть в sql запросах. 

Например, если ее сделать varchar(255), то можно легко выйти за ее пределы.

У нас на проекте было так сделано очень давно в фотоальбомах. ИД фотографий хранился в поле через запятую, и доставался через explode(). При этом было 100500 костылей, когда нагрузка выросла и кол-во фоток в альбомах превысило 500. Сейчас мы переделали более грамотно - вынесли в отдельную сущность фотографии и при необходимости получаем их вторым запросом.

Автор: ksnk 7.3.2013, 14:36
Цитата(Aliance @  7.3.2013,  13:24 Найти цитируемый пост)
ИД фотографий хранился в поле через запятую, и доставался через explode()

Поле `text`. Размером не более 4к, впрочем, это опционально.
Никто их никогда не эксплодит, это готовая запчасть запроса.

Автор: Sanchezzz 7.3.2013, 19:26
если нужно через запятую что то найти в БД то как я помню там есть функция: FIND_IN_SET(:id,`column_name`)

В SMF форуме прочитанное для реганых узеров хранится в лог таблице, которая чистится при добавление новых постов для конкретной темы

К запросу добавляются только когда авторизованный пользователь части запроса.

Код

Select 
  1 AS is_read  -- для гостей что бы undefined variable не было 
    -- эта часть запроса вставляется когда пользователь авторизован. 
  IFNULL(lt.id_topic, 0)  AS is_read
  FROM topics t 
  INNER JOIN messages AS m ON (m.id_msg = t.id_last_msg)
   -- эта часть запроса вставляется когда пользователь авторизован. 
   LEFT JOIN log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member =:current_member)

Если лог таблица будет периодически чистится то не будет тормозов. 


  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)