Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Лучшие практики для пагинации контента

#ajax #база_данных #постраничный_вывод


Есть определенные записи в базе данных(mysql, но не принципиально), которые выводятся
постранично или подгружаются через ajax(в рамках задачи это не имеет значения). 

Записи выводятся в зависимости от рейтинга(по убыванию). Рейтинг записи могут изменять
пользователи ресурса.

Каким образом лучше всего избежать дублирования вывода записей при переходе на другую
страницу или подгрузке новых? 

Пример.

Допустим, у нас в базе следующий список записей:

Запись №1 - рейтинг 15

Запись №2 - рейтинг 14

Запись №3 - рейтинг 13

Запись №4 - рейтинг 12

Запись №5 - Рейтинг 11

Запись №6 - рейтинг 0

Допустим, на странице выводится за раз по 5 записей. 
То есть при первом заходе на страницу у нас будут выведены следующие записи и в таком
порядке - №1,№2,№3,№4,№5(в порядке убывания рейтинга). Если теперь, когда пользователь
ещё находится на этой странице, изменится рейтинг записи №6, например, на 20, то на
второй странице будет выведена запись №5 снова, что не правильно. 

Как решить данную проблему лучше всего?

Мне в голову приходит вариант с передачей каждый раз номеров уже выведенных записей
и второй - кэширование, но оба кажутся не совсем верными. Как решают подобные проблемы
на крупных проектах с большой активностью пользователей? Язык и БД особо не играет
роли, интересен только подход.



Голоса пользователей хранятся в отдельной таблице: 

id user_id record_id date

Записи соответственно в таблице record:

id rating 

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


Ответы

Ответ 1



1 вариант. Можно кешировать результат. (например memcache).Следующим образом. В ИД кеша используется временная метка. Т.е. я зашел на первую и поучил временную метку. При дальнейшем моем обращении я получаю закешированные данные с этой временной меткой. При изменении рейтинга организуется новый кеш с новой временной меткой. Если развить этот подход, то можно попробовать только затронутые изменением страницы. В любом случае это не полное описание реализации, а идея, которую можно развить 2 вариант. Хранить историю рейтинга с временными метками в отдельной странице. И опять же обеспечить передачу на сервер (параметр, кука или переменная в сессии) временной метки с которой мы работаем. Так же можно скидывать куда то метки с которыми сейчас работают посетители. А другим скриптом на кроне чистить историю, которая ни кому не нужна. Но, на мой взгляд, все это лишние сложности. А может лучше показать посетителю: "Дружище изменился рейтинг"? Например, по простому, хранить в сессииИД записей что были на посещенной странице и если какаято из них окажется на странице на которую перешли то выдать меседж... Либо все теже мемкеш. В него записываем ИД записи у которой изменился рейтинг. При открытии новой страницы показываем сообщение" У записи ссылка изменился рейтинг..... Это заодно повысит "глубину просмотра" ;)

Ответ 2



Для больших проектов есть инструменты. Например, у нас много таблиц с большим количеством записей: ag-grid + OData. Это готовые, проверенные инструменты на все случаи жизни. В описанном примере вижу два решения: 1) Статика. При обновлении записи кидать нотификацию пользователю, что рейтинг изменился. Не пускать новые данные - сделать кнопку обновить таблицу, при нажатии на которую произойдёт обновление. 2) Динамика. При выводе записей сохранять на стороне клиента Id выведенных записей. Если на сервере произошло обновление рейтинга, то сервер шлёт нотификацию клиенту, в которой содержатся Id записи, для которой обновился рейтинг и значение рейтинга. Если этот Id среди выведенных, то на клиенте производим обновление текущей страницы, иначе игнорируем. Обновление можно сделать либо с помощью ещё одного запроса на сервер, либо с помощью клиентского кода(js,ts,...). Выбор одного из вариантов обуславливается использованием, например, 1-й хорошо подойдёт, если предполагается, что пользователь делает снапшот рейтинга на момент времени, 2-й если нужна страница с постоянными актуальными рейтингами. Можно поставить чекбокс: статика/динамика и реализовать оба варианта. Вариантов использования придумать можно гораздо больше. Следующий вопрос будет к нагрузке на сервер. 1-й в отличии от второго не требует нотификации браузера со стороны сервера, что является плюсом, и если динамическое обновление не важно, то стоит выбрать его. Кстати, не думаю, что вывод номера 5 на 2-й страницу это неправильно, потому что какой толк в сортировке, если она не выводит записи на своих местах?

Комментариев нет:

Отправить комментарий