Работа с социальными данными. Персонализированная выдача. Ранжирование результатов выдачи по нескольким критериям


(Игорь Кожаров) #1

Здравствуйте, есть следующий кейс, индекс содержит данные о пользователях. Ищем по полному или частичному совпадению в username или full_name. В приоритете совпадения в username. Результат нужно сортировать по нескольким критериям, я имею в виду, что первыми должны быть результаты с полным совпадением в username или full_name. Далее необходимо первыми показать тех пользователей, у которых есть связи с автором запроса, по типу сначала друзей, потом друзей друзей, критерий ранжирования в этом случае количество общих связей. И в завершении показать популярных пользователей.

Данные о связях берутся из другого места, так что на elasticsearch ложится только задача поиска и сортировки.
На данный момент пользуюсь решением с помощью function score query.
https://www.elastic.co/guide/en/elasticsearch/reference/2.1/query-dsl-function-score-query.html
Как бы вы подступились к этой задаче? Есть ли зарекомендовавшие себя подходы?


(Igor Motov) #2

Я думаю, проще всего начать с подхода, описанного в этой теме. Если что-то не будет работать, присылайте пример и будем разбираться, что не работает.

Хочу только предупредить, что выборка связи из другого места - дело хитрое, потому что без локального кеширования вам придется проверять связь для большого количества пользователей через сеть. Причем, запросы должны будут посылаться по одной записи последовательно в каждой шарде. Так что, даже если вы сможете выполнять каждую проверку за пол миллисекунду (время пересылки пакета в одном и том же ВЦ), выполнение этой проверки для 10,000 пользователей займет 5 секунд. Вы не сказали о каком масштабе идет речь, так что в зависимости от размера вашего индекса это может и не быть серьезной проблемой.

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

Другой способ - это индексировать информацию о связях в elasticsearch. Переиндексировать каждую запись при изменении связи не реалистично. Но индексировать небольшую child запись с id друга вполне возможно. Этот подход хорошо работает если важена только прямая связь. С друзьями друзей популярные пользователи, к сожалению, вызывают проблему в лубом случае (если не ограничивать количество друзей или не игнорировать некоторых друзей, если их накопилось слишком много).


(system) #3