如何使用ElasticSearch实现社交搜索?

时间:2012-05-21 16:28:33

标签: elasticsearch

我正在尝试使用ElasticSearch创建具有社交功能的商业搜索。我有一个商业目录,用户可以通过不同的方式与这些商家进行互动:通过查看,检查它们等等。

当用户搜索商家时,我希望能够向他们展示他们的朋友在搜索结果顶部与之互动的商家(或根据这些互动进行过滤)。 设置索引以实现此目的的最佳方法是什么?

我认为有一些可能的解决方案,但我是ES的初学者,我不确定会导致什么问题:

  1. 我可以使用多租户并为每个用户创建一个单独的索引。我已经排除了这一点,因为用户数远远大于业务量或用户特定内容的数量。

  2. 我可以为每个索引的商家添加一个用户/分数对列表。每个与业务进行过互动的用户都会在那里,分数将代表他们与业务进行的互动量(这对我的过滤/排序来说已经足够了)。每次他们与业务交互时,我都会更新索引中的分数。这个问题是我只关心朋友的活动,所以我需要找出一些方法来考虑我的朋友在为业务创建综合评分时是谁。我不知道如何在ES中这样做。

  3. 我可以创建一个类似的方案,但不是保持我与业务的互动得分,分数将反映我的朋友与业务的互动。这消除了在ElasticSearch中对社交图进行建模的需要,但它确实意味着每当一个人与一个企业进行交互时,我都需要更新他们所有朋友的分数。这也意味着每个企业的用户/分数对列表会更大,因为它需要包含任何有朋友与企业互动的人。

  4. 我能想到的最终解决方案是跟踪企业发生的每一次交互,并将其添加到ES中的业务文档中。这对我来说似乎不太现实 - 它结合了其他解决方案的问题。但就保持指数最新而言,这可能是最简单的方法。

  5. 感谢您的帮助!

5 个答案:

答案 0 :(得分:8)

我正在投票修改#2。

我不会将每个用户/分数对存储在业务文档本身中,而是创建父/子关系。这使您可以更新孩子的分数(用户分数),而无需重新索引整个业务文档(以及所有其他用户分数)。

查看此页面,了解一个很棒的教程,父母/孩子大约有一半的时间:http://www.spacevatican.org/2012/6/3/fun-with-elasticsearch-s-children-and-nested-documents/

然后,您可以使用has_child filtertop_children query来查找您的朋友有分数的商家。有关订购儿童文档的一些注意事项,但该教程涵盖了这一点,因此请务必阅读底部。

然后我只对所有“非社交”排名搜索执行正常查询。

或者,您可以将所有内容混为一谈,并为您的朋友所进行的比赛添加提升,以便所有内容都适当排名。执行两个查询并自己组合可能会更容易。

答案 1 :(得分:5)

还有另一组解决方案具有极快的优势(即利用ES最擅长的优势),但对于那些甚至不知道设计数据存储/检索系统的人来说,这看起来很糟糕。

如果您的“商家”指数小于“用户”指数(即10,000个商家,1,000,000个用户)

  1. 创建2个索引:用户业务
  2. 商业索引应该有一个'数组'字段,用于保存每个曾与之“互动”的用户的ID(即“用户:1,4,23,26,127,8678”)
  3. 用户索引应该有一个嵌套数组字段,其中包含带有元信息的嵌套对象中的业务ID和评论,签到等(即“business_id:1233,rating:7.5,checkins:21”)
  4. 当您搜索商家时,请使用用户的朋友ID(当然是OR)对商业索引进行快速字符串查询或过滤查询。 tf-idf应自动过滤您的朋友最常互动的商家。如果您需要更多信息,只需点击用户索引即可获取每位朋友的元数据(评分,签到等)。这应该是快速和超高效的闪电,因为ES绝对是将数组作为单独术语进行匹配的绝佳选择。这就是它的哟!

    如果您的“业务”索引明显大于“用户”索引,请反转模式...将用户与用户索引进行交互的business_id索引数组放在一起。

答案 2 :(得分:5)

查看Titan https://github.com/thinkaurelius/titan/wiki/Using-Elastic-Search

它有一个图形引擎,可以作为后端使用Elasticsearch。你可以像(我)一样进行图遍历 - > (朋友) - [评论] - > (业务)找到所有这些连接并调整搜索的等级。

答案 3 :(得分:3)

这里只是spitballing但是我想我想要使用像Neo4J这样的图形数据库,在这里查询“我的朋友已经检查过的商家”这样的查询并同时查询该数据库和elasticsearch是很容易的首先从图表数据库返回结果。或者您可以获得该图形查询的结果并匹配elasticsearch中的结果(匹配ID),然后对弹性搜索结果应用查询时间提升,以便它们浮动到返回结果的顶部。

答案 4 :(得分:1)

Solr可以使用GraphQuery运算符执行此操作。

https://issues.apache.org/jira/browse/SOLR-7543

它允许您将文档放在索引中,其中包含" node_id"的字段。和#34; edge_id"

的(多值)字段

有几种方法可以解决这个问题:

  1. 您可以拥有一个包含朋友ID列表的用户文档。或
  2. 您可以拥有一个单独的表,该表是用户记录之间链接的链接表。
  3. 对于案例1:使用包含" user_id"的字段为系统中的每个用户索引文档。和另一个包含" friend_ids"。

    的字段

    此时为用户555搜索所有朋友将是:

    {!graph from="user_id" to="friend_ids" maxDepth=1}user_id:555
    

    寻找用户朋友的朋友

    {!graph from="user_id" to="friend_ids" maxDepth=2}user_id:555
    

    如果您在用户记录(例如位置字段)上有其他元数据字段,则可以将其添加为遍历过滤器以查找住在波士顿的朋友。此遍历过滤器应用于每一跳。

    {!graph from="user_id" to="friend_ids" maxDepth=2 traversalFilter="location:Boston"}user_id:555
    

    以上查询会发现居住在波士顿的朋友是住在波士顿的朋友用户555.