За последние 24 часа нас посетил 18251 программист и 1634 робота. Сейчас ищут 1716 программистов ...

Реализация "новых" тем в форуме

Тема в разделе "Решения, алгоритмы", создана пользователем antonn, 21 июн 2007.

  1. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    armadillo, не, это слишком жестокий фильтр :) кто такой дайджест?

    вообще, не мог бы ты более развёрнуто говорить, а то моя твоя не понимать :)
     
  2. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    птичка "добавить этот форум в дайджест". И тогда по нему строится история посещений и поднятые темы показываются в списке последних. Остальные разделы тихо сидят и не отсвечивают. Захотел - и отписал раздел "флейм" из дайджеста.
     
  3. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
  4. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Фишка в том, что в форуме есть не только темы, по которым у меня есть связки в forums_last_readed о прочитанных темах, но и есть просто новые темы, в которые я никогда не входил.
    Вопрос вот именно в том, как имея одну запись ID форума; ID юзера; сделать так, что бы ему 100% достоверно показывало, что там либо что-то есть, либо нету. Держать запись типа:
    USER ID; FORUM ID; 1/0;
    Не проблема, вопрос в том, КАК определить что в форуме я прочитал все темы и новых сообщений там НЕТ. Если тыкать в кнопку "Отметить форум как прочитанный" - оке, no problemo. А если там было:
    3 темы за которыми я слежу с новыми сообщениями и 5 новых тем. Просмотрю я все 8. Как мне определить при просмотре 8-й темы, что новые сообщения кончились? При входе в форум выбирать что-ли ID'ки всех непросмотренных тем и вогнать их в сессию и по мере просмотра тем удалять из массива просмотренные темы и как только их кол-во будер равно 0, апдейтим запись USER ID; USER FORUM; 0; ? Единственное, если форум большой и много обновлений, в вессии будет таскаться довольно большой массив.

    З.Ы. Между прочим неплохая идея, надо будет попробовать :)
     
  5. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    добавление поста
    [sql]insert into юзеры*темы select ".$topic_id.", ".$post_id.", user_id from users left join юзеры*темы ut on ut.topic_id=".$topic_id." and ut.user_id=users.user_id where ut.user_id is null[/sql]
    новой темы - еще проще.

    просмотр темы
    [sql]delete from users_topic where user_id=".$user_id." and topic_id=."$topic_id[/sql]
    [sql]select count(ut.topic_id) as viewedforum from users_topic ut, topics t
    where ut.user_id=."$iser_id."
    ant ut.topic_id=t.topic_id
    and t.forums_id=.$fid[/sql]
     
  6. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    хм.. почитал, подумал.
    А как такой вариант. Есть две дополнительные таблички, в одной хранится маркер для категории в целом (id юзера/id форума/upper_date/lower_date)(у меня форум разделен на категории просто, без вложений), в другой маркер для темы (id темы/id форума/id юзера). А upper_date и lower_date являются ограничивающими датами в выборке. Примерно так:
    Код (Text):
    1. все темы, что выше этой даты - все непрочитанные
    2. //upper_date
    3.  
    4. если в этом интервале и есть маркер на тему - прочитана, иначе - непрочитанная
    5.  
    6. //lower_date
    7. все темы, что ниже этой даты - всегда прочитаны
    если мы щелкаем на тему выше верхней даты - верхней дате присваиваем значение даты темы, плюс создаем маркер для этой темы(прочитана).
    если щелкаем на тему в интервале - создаем маркер.

    если заходит новый юзер - нужно все темы пометить как прочитанные (я так думаю:) ) - просто в маркер для форума для граничных дат выставить текущее время.

    lower_date автоматически можно присваивать от темы, выше всего лежащей от нее без непрочитанных Т.е.
    Код (Text):
    1. прочитано 1
    2. непрочитано 2
    3. прочитано 3
    4. прочитано 4
    5. //lower_date
    lower_date можно присвоить дату из номера 3.

    все маркеры темы ниже lower_date легко удаляются одним запросом.

    если в интервале от граничных дат все маркеры (прочитаны) - для обоих дат присваиваем значение верхней граничной даты и удаляем маркеры.

    вот теперь все это реализовать надо. "Деревянным" методом вроде получается, это когда тупо куча запросов, вложенные циклы (это все от малознания:) ).
     
  7. Anonymous

    Anonymous Guest

    antonn, так в том и проблема, собственно ))
    Либо - избыток хранимых данных в угоду сложности, либо — большое количество запросов, либо сложный парсинг строк регулярками... и везде условия, типа — 2 недели устаревания, и т.п.
     
  8. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    Горбунов Олег
    ну пока получается на каждую страницу списка тем форума 3 запроса и при просмотре темы 2 минимум (плюс на каждый маркер, если его создавать - по запросу). Решил, что лучше я сделаю маркеры темы отдельным записями, а не серилизованным массивом в записи для целого форума в текстовом виде...

    дурацкий вопрос:) 32 запроса на то, чтобы нарисовать страницу сайта - это нормально? :)
     
  9. Anonymous

    Anonymous Guest

    кроме числа запросов, есть еще число строк, которые прийдется просмотреть - а это тоже процессорное время
    зависит от сложности и структуры. но, имхо, многовато....
     
  10. Anonymous

    Anonymous Guest

    Обсуждение получается интересное, перенесу и закреплю.
     
  11. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    практика показывает, что "нинада эта!"
    новые темы будут достоверно показываться. а старые непросмотренные - не актуальны, так как за всё это время пользователь так и не удосужился её просматреть.

    а ты хочешь и на ёлку влезть и не поцарапаться? =)
     
  12. Davil

    Davil Guest

    Халтуришь :lol:
     
  13. Anonymous

    Anonymous Guest

    ну, к этому надо стремится =))
     
  14. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    вариант 1
    старые непросмотренные пишем в базу.
    просмотренные удаляем.
    недосмотренные пишем.
    Недостаток:
    большой объем на непросмотренные темы.
    Вариант 2
    пишем просмотренные (с флагом) и недосмотренные.
    Недостаток: большой объем на все просмотренные темы. Не уверен, что будет намного больше чем просто список недосмотренных - большинство юзеров не так активны.
    Вариант 3.
    пишем недосмотренные, просмотренные удаляем.
    несмотренные вообще храним в бинарном поле - допустим 16-32к на юзера, 128-256к ид тем.
    на 50к юзеров объем 32к*50к=1.5гб. упс. ))
     
  15. antonn

    antonn Активный пользователь

    С нами с:
    10 июн 2007
    Сообщения:
    2.996
    Симпатии:
    0
    armadillo
    все оптимизируется вводом двух ограничивающих дат, см. Пт Июн 22, 2007 10:45.
    нижняя дата устанавливаем минимум, от которого будут создаваться маркеры просмотренных тем (я решил хранить именно просмотренные), и эта дата постоянно увеличивается (при условии активного пользователя), даже не надо устраивать пассивное ограничение в 2 недели (хотя можно на всякий случай месяц там поставить). Все темы ниже этой даты считаются прочтенными всегда (и ведь да, если в какой то старой теме будет изменение - значение даты у нее изменится на большую, чем ограничение).
    Верхняя дата устанавливает границу сверху, выше которой темы считаются свежими всегда - если пользователь отсутствовал долго и зашел, то не нужно создавать кучу маркеров - они все равно помечены как не прочитанные.
    Ну а на те, что входят в интервал, создавать маркер в случае просмотра темы (плюс в маркер я пихаю дату последнего изменения темы - по этой дате можно определить последний просмотренный пост, ведь следующие новые посты будут с большей датой), а так же обновлять дату изменения в маркере, если он существует.

    Только нужно учесть несколько заковырок.
    При просмотре темы:
    Если выбирается тема выше up_date (верхняя дата), то нужно создать для нее маркер (либо обновить существующий - тема может быть старой, но обновленной). Для up_date установить значение даты изменения этой темы (поднимаем границу верхней даты выше - теперь, все новые темы, что попали в обновленный интервал дат - они автоматически свежие, ведь для них нет маркера в интервале!).
    Если выбирается тема в интервале ограничивающих дат, нужно также либо создать маркер для нее (либо обновить существующий). С маркером в интервале тема считается прочитанной.

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

    Теперь я просто создаю массив непрочитанных тем(именно не прочитанных, на его основе уже рисуется сам форум на хтмл) по такому принципу (делаю выборку по всем маркерам для форума+юзера):
    если маркер лежит в интервале граничных дат и дата его последнего изменения не совпадает с датой изменения темы - в массив (ведь это значит, что тема была изменена)
    если маркера нет - в массив (тема значит свежая, раз маркера нет)
    если дата изменения темы выше, чем верхняя граничная дата - в массив (все что выше верхней даты - автосвежее)

    итого, имеем массивчик, в котором лежат непрочитанные темы, в кач. ключей делаю id темы. при рисовании форума, просто делаю array_key_exists() для нужной темы - есть ключ - тема помечается как непрочитанная.
     
  16. ONK

    ONK Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    281
    Симпатии:
    0
    Адрес:
    СПб
    Нет смысла пытаться установить точный факт отсутствия непрочитанных тем в целом форуме. В большом форуме всегда будут непрочитанные темы, и как следствие он всегда будет подсвечен как не прочитанный. Даже в небольшом форуме я читаю далеко не все темы, как результат - в форуме нет ничего для меня интересного, а он подсвечен как непрочитанный.
    Я пришёл к выводу, что достаточно проверять факт прочитанности самой "свежей" темы форума, и на основании него подсвечивать форум или нет.
     
  17. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    опять же, не спасает от актуальных, но неинтересных тем.
    лично я пришёл к выводу, что подсвечивать форум - нафиг не надо. достаточно просто под списком форумов выводить последние N тем в них.
     
  18. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    еще раз - я прочел тему за вчера, но оставил на сладкое позавчерашнюю. Форум прочитан?
    Главная не перегружена?
     
  19. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
  20. dark-demon

    dark-demon Активный пользователь

    С нами с:
    16 фев 2007
    Сообщения:
    1.920
    Симпатии:
    1
    Адрес:
    леноград
    armadillo, нет, не перегружена.
     
  21. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    не то.

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

    1) новый юзер.
    Все темы не прочитаны. пишем только инфу о прочитанных заново темах.
    поднимаем флаг "не сохраняем нечитанные"
    пишем в лог прочитанные ветки
    (пишем ид_последнего поста в лог)

    2) нажата кнопка "пометить все прочитанным".
    Сохраняем дату нажатия кнопки.
    поднимаем флаг "не сохраняем нечитанные".
    проверяем темы а) по дате. б) по факту прочтения.
    (пишем ид_последнего поста в лог)

    3) прошел год после нажатия кнопки "пометить все прочитанным"
    юзер прочел 5к тем, из них 100 сейчас актуальны, остальные читанные и нечитанные утопли.
    формат хранения полей таблицы с просмотрами - binary или varbinary по 32бит.
    user_id, topic_id, post_id
    возможно добавления тех же полей в таблицы users, topics, posts

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

    вопрос как сократить объем инфы по полностью прочитанным веткам.
    разбить на два запроса и хранить в отдельной таблице?
    user_id,topic_id
     
  22. ONK

    ONK Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    281
    Симпатии:
    0
    Адрес:
    СПб
    Да, форум прочитан, если ты запомнил, что хочеш что-то ещё прочитать, прочитай это когда будет время, но для движка форума особенности методов прочтения тем различными пользователями не должен иметь значения, сканировать все темы форума в поисках не прочитанных - бессмыслено. Я не читаю 99% тем большинства посещаемых мною форумов.
     
  23. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    Интересно, а как функция новых сообщений реализована в phpBB?
     
  24. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    [vs]
    По-дурацки :D у меня регулярно глючит на этом форуме.
     
  25. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.559
    Симпатии:
    632
    А в IPB?