Pull to refresh

Алгоритм рейтинг листа.

Reading time2 min
Views1.3K
Доброе время суток, уважаемое хабросообщество.
В процессе создания одного проекта столкнулся с проблемой реализации рейтинга пользователей. В принципе, можно провести аналогию и с Хабром. Дело в том, что пользователь рейтенгуется в соответствии с неизвестным алгоритмом и получает какой-то показатель (хабрасила, мы назовём его рангом). После чего формируется лист, упорядоченный по убыванию этого показателя. Вроде бы всё просто.
  • Имеем n параметров, от которых зависит ранг. При изменении любого из параметров пересчитываем ранг.
  • Для отображения топ-листа делаем простой select из базы данных с order'ом по рангу.
Вроде бы всё выглядит, проще некуда. Но тут появляются несколько проблем.
  • Хотелось бы заранее знать позицию пользователя в рейтинге. Например, для отображения в профиле, создания личного информера и т.п.
  • При клике на ссылку из профиля, хотелось бы попадать именно на ту страничку топ листа, которая содержит нашего пользователя (чего нет даже на Хабре).
Вторая проблема, в теории, зависит от первой. Ведь зная позицию пользователя и количество отображаемых на странице, мы можем расчитать в какой именно части рейтинга он находится.
необходимая_страница = округление_в_большую_сторону( позиция / количество_на_странице )
Но тогда появляется вопрос, как же высчитывать позицию? Она должна быть релевантная ко всем остальным пользователям.
Одним из решений является отдельный скрипт, запускаемый раз в определённый промежуток времени, который будет делать огромную выборку из базы с order'ом по рангу (подразумевается, что он всегда актуален). После чего присваеваем каждой записи порядковый номер и сохраняем его в базу. Вариант рабочий, но имеет существенные недостатки.
  • При больших количествах скрипт будет сильно грузить базу данных.
  • Такой рейтинг актуален только на момент выполнения скрипта. При большой скорости движения пользователей в рейтинге, реальная позиция может измениться ещё до того, как скрипт завершит свою работу.
На ум приходит мысль, что подсчёт позиции должен происходить на момент открытия пользовательского профиля. При этом, он не должен делать сложных запросов к базе данных. Это бы решало все поставленные задачи, но как такое реализовать, я не знаю. Топик запостил для того, чтобы разобраться с задачей вместе с Хабражителями. Тут много людей, которые могут помочь и не меньше, которым это будет интересно знать. Так что ждём комментариев. Текст буду обновлять по мере того, как будет что-то проясняться.

UPD. Eyes предложил решение для определение позиции на лету. Так как мы уже имеем поле в таблице пользователя с параметром ранг, для определения позиции пользователя нам всего лишь необходимо сделать select count(*)… where… and rank > user_rank.

UPD 2 С найденым решением появилась новая проблема. Как разделять пользователей с одинаковым рейтингом? Ведь количество юзеров с рейтингом больше, для них одинакого.
Можно просто не обращать на это внимание и давать им одно и то же место. Так сделано на хабре. Для примера можно посмотреть на профили этих пользователей: NooL и Zada. Не знаю, долго ли они продержатся на равне, но суть в том, что они оба 983ие в рейтинге.
По идее, так даже правильнее, нет дискриминации между пользователями с одинаковым рейтингом, но как тогда ссылаться на середину списка, не зная точной позиции?

P.S. Знаю, что Хабр — не форум, но я очень сильно заинтересован в разрешении поставленной задачи, что делает кармориск оправданным.
Tags:
Hubs:
Total votes 9: ↑9 and ↓0+9
Comments40

Articles