20

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

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

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

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

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

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

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

谢谢你的帮助!

4

5 回答 5

8

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

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

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

然后,您可以使用has_child 过滤器top_children 查询来仅查找您的朋友得分的那些企业。关于订购子文档有一些注意事项,但该教程已涵盖它,因此请确保您阅读到底部。

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

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

于 2012-08-01T04:20:53.217 回答
5

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

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

于 2014-04-15T18:41:56.507 回答
5

还有另一组解决方案具有非常快的优势(即利用 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 的索引数组放在用户索引上。

于 2012-09-02T13:22:21.827 回答
3

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

于 2013-05-20T20:33:07.240 回答
1

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 的朋友。

于 2016-02-15T20:04:11.630 回答