3

我正在开发一种在 Ruby on Rails 中的个性化搜索引擎,我目前正在尝试根据用户的记录实时找到对结果进行排序的最佳方式。

示例:搜索的项目可以有标签(带有 id 的单独实体),例如项目有标签=[1,5,10,23,45]。

另一方面,用户可能已将某些标签标记为特别感兴趣,因此假设用户的标签=[5, 23]。

用于对结果进行排序的分数应考虑用户“盯着”的项目标签的数量。例如,项目的分数将基于项目的属性为 50%,而排名为 50%,具体取决于用户的(注视的标签数量)。

一个想法是将其注入信息检索系统的排序功能中。但是在我可能会使用的 Sphinx 中,实现起来会非常尴尬(当用户的向量很大时)。我不了解 Lucene/solr,但它们似乎没有我需要的高级非文本搜索功能(距离、日期、时间等)

其他选项是从 IR 系统检索中介集,然后在应用程序级别对其进行处理。但是,我很确定按顺序处理 100-1000 条记录,然后在 Rails 中对它们进行排序会非常慢。

另一方面,这似乎是可以轻松并行处理的任务 - 将 1000 条记录分成由单独的线程处理然后排序的集合。

我读到了几个 map reduce 实现,既有像 hadoop 这样的通用实现,也有像 skynet 等特定于 rails 的实现,但它们最适合大批量作业,而不是实时处理(除非我弄错了?)。

我可以为此使用任何内存中的轻型 MR 实现吗?或者,也许你有一些其他的想法如何处理它?

(旁注:我相信这个设置类似于谷歌新闻的工作方式,从我从“谷歌新闻个性化:可扩展的在线协同过滤”论文中了解到。它们实时匹配一组候选故事和用户所属的一组集群到(之前预先计算的)以个性化的方式对故事进行排序)

4

1 回答 1

1

Map/Reduce 非常适合这种事情,但您可以使用中间表在 SQL 中处理它。

大概,你已经有这样的表:

用户(ID,...)
项目(id,...)
标签(id,...)
users_tags (user_id, tag_id)
items_tags (item_id, tag_id)

所以,你为什么不也维护一个这样的表:

users_items_tags (user_id, item_id, tag_id)

其中每一行的意思是“这个用户和这个项目共享这个标签”。

然后,您的搜索查询是这样的:

  选择 item_id, count(tag_id) 作为分数
    来自 users_items_tags
   其中 user_id = <USER_ID>
按 item_id 分组
按分数顺序排列

当用户添加标签时,users_items_tags更新如下:

插入 users_items_tags (user_id, item_id, tag_id)
     选择 <USER_ID>、item_id、<TAG_ID>
       来自 items_tags
      其中 tag_id = <TAG_ID>

在向项目添加标签时也是如此。删除标签时,只需删除标签和用户/项目。

此解决方案有一些问题案例。如果某个特定标签在项目中是常见的,那么当用户添加该标签时将执行大量写入,反之亦然。如果标签在项目和用户中都是通用的,那么表格将变得非常大。您必须为您的特定数据集考虑这些情况。

于 2008-12-05T07:46:33.527 回答