Параллельная обработка RT в Rails - PullRequest
3 голосов
/ 25 ноября 2008

Я разрабатываю своего рода персонализированную поисковую систему в Ruby on Rails и сейчас пытаюсь найти лучший способ сортировки результатов в зависимости от записи пользователя в режиме реального времени.

Пример: искомые элементы могут иметь теги (отдельные объекты с идентификаторами), например, элемент имеет теги = [1, 5, 10, 23, 45].

Пользователь, с другой стороны, мог отметить некоторые теги как представляющие особый интерес, например, у пользователя есть теги = [5, 23].

Оценка, используемая для сортировки результатов, должна учитывать количество тегов элемента, которые «смотрятся» пользователем. Например, оценка предмета будет 50% в зависимости от атрибутов предмета и 50% в зависимости от ранга в зависимости от пользователя (количество сохраненных тегов).

Одна идея заключалась в том, чтобы внедрить это в функцию сортировки в информационно-поисковой системе. Но в Sphinx, который я, вероятно, буду использовать, было бы очень неудобно реализовывать (когда вектор пользователя велик). Я не знаю о Lucene / solr, но, похоже, они не обладают расширенными возможностями нетекстового поиска, которые мне все равно нужны (расстояние, дата, время и т. Д.)

Другой вариант - получить промежуточный набор из системы IR, а затем обработать его на уровне приложения. Однако я совершенно уверен, что последовательная обработка 100-1000 записей и последующая их сортировка в Rails будут очень медленными.

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

Я читал о нескольких реализациях сокращения карт, как универсальных, таких как hadoop, так и специфичных для rails, как skynet и т. Д., Но они лучше всего подходят для больших пакетных заданий, а не для обработки в реальном времени (разве я не ошибаюсь?).

Есть ли какая-нибудь легкая МР-реализация в памяти, которую я мог бы использовать для этого? Или, может быть, у вас есть другие идеи, как с этим справиться?

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

1 Ответ

1 голос
/ 05 декабря 2008

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

Предположительно, у вас уже есть такие таблицы:

users (id, ...)
items (id, ...)
tags (id, ...)
users_tags (user_id, tag_id)
items_tags (item_id, tag_id)

Итак, почему бы вам также не вести такую ​​таблицу:

users_items_tags (user_id, item_id, tag_id)

, где каждая строка означает "этот пользователь и этот элемент имеют общий тег".

Тогда ваш поисковый запрос будет выглядеть примерно так:

  select item_id, count(tag_id) as score
    from users_items_tags
   where user_id = <USER_ID>
group by item_id
order by score desc

Когда пользователь добавляет тег, users_items_tags обновляется следующим образом:

insert into users_items_tags (user_id, item_id, tag_id)
     select <USER_ID>, item_id, <TAG_ID>
       from items_tags
      where tag_id = <TAG_ID>

и при добавлении тега к элементу. Когда тег удален, просто удалите тег и пользователя / элемент.

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

...