【问题标题】:How can ElasticSearch be used to implement social search?如何使用 ElasticSearch 实现社交搜索?
【发布时间】:2016-12-11 18:12:15
【问题描述】:

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

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

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

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

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

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

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

感谢您的帮助!

【问题讨论】:

  • 我遇到了类似的问题 - 请分享一下您最终是如何解决的?

标签: elasticsearch


【解决方案1】:

我投票支持修改后的#2。

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

查看此页面以获取很棒的教程父母/孩子大约一半:http://www.spacevatican.org/2012/6/3/fun-with-elasticsearch-s-children-and-nested-documents/

然后,您可以使用has_child filtertop_children query 仅查找您的朋友有得分的企业。关于订购子文档有一些注意事项,但该教程已涵盖,因此请务必阅读到底部。

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

或者,您可以将所有内容放在一起,并为您朋友得分的比赛添加助推器,以便所有内容都得到适当的排名。执行两个查询并自己组合它们可能会更容易。

【讨论】:

    【解决方案2】:

    还有另一组解决方案具有极快的优势(即利用 ES 最擅长的方面),但对于任何了解设计数据存储/检索系统的第一件事的人来说,这看起来很糟糕。

    如果您的“业务”索引小于“用户”索引(即 10,000 个企业,1,000,000 个用户)

    1. 创建 2 个索引:UserBusiness
    2. 业务索引应该有一个“数组”字段,其中包含曾经与其“交互”过的每个用户的 ID(即“用户:1,4,23,26,127,8678”)
    3. 用户索引应该有一个嵌套数组字段,其中包含业务 ID 和评论、签到等,位于包含元信息的嵌套对象中(即“business_id:1233,rating:7.5,checkins:21”)

    当您搜索业务时,使用用户的朋友 ID(当然是 OR)对业务索引执行快速字符串查询或过滤查询。 tf-idf 应该自动将您的朋友与您互动最多的企业过滤到顶部。如果您需要更多信息,只需点击用户索引即可获取您每个朋友的元数据(评分、签到等)。这应该是快速且超级高效的,因为 ES 非常擅长将数组作为单独的术语进行匹配。这就是给你的!

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

    【讨论】:

    • 我对ES还比较陌生,但是当你创建用户索引时,你不是免费获得用户索引吗?基本上,业务索引是用户索引中business_id字段的反向索引
    【解决方案3】:

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

    它有一个图形引擎,可以使用 Elasticsearch 作为后端。您可以像 (me) -> (friend) -[review]-> (business) 那样进行图遍历,以找到所有这些联系并调整搜索的排名。

    【讨论】:

      【解决方案4】:

      只是在这里吐口水,但我想我想使用像 Neo4J 这样的图形数据库,在其中执行诸如“我的朋友已签入的企业”之类的查询并同时查询该数据库和 elasticsearch 将是微不足道的时间并首先从图形数据库返回结果。或者您可以只获取该图形查询的结果并在 elasticsearch 中匹配结果(匹配 id),然后对弹性搜索结果应用查询时间提升,以便它们浮动到返回结果的顶部。

      【讨论】:

        【解决方案5】:

        Solr 可以使用 GraphQuery 运算符来做到这一点。

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

        它允许您将包含“node_id”字段和“edge_id”(多值)字段的文档放入索引中

        有几种方法可以构建它:

        1. 您可以拥有一个包含朋友 ID 列表的用户文档。或者
        2. 您可以有一个单独的表,它是一个链接表,用于链接用户记录。

        对于案例 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 的朋友。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-23
          • 2020-02-16
          • 2023-01-01
          相关资源
          最近更新 更多