如何为Elasticsearch

时间:2017-03-02 21:00:03

标签: elasticsearch

我本质上是在尝试模仿ES中的连接,我知道这不是ES的一个很好的用例,但与此同时,我想要完成的事情似乎与众不同搜索功能。我已经阅读了ES文档,博客文章,绘制的图表,当然还在本地测试了不同的场景,但是我仍然很难理解如何为ES索引这些数据。这是我的第一个ES项目,也是我第一次与noSQL环境进行真正的互动。

想象一下社交食谱网站(为简单起见)......

用户可以发布原始食谱。其他用户可以“喜欢”(一次),“保存到”(多次保存到不同类别)和“烹饪”(可以多次烹饪食谱)食谱。

用户可以搜索食谱并在不同的简单标志上过滤它们,例如“食谱至少已煮熟一次”,以及他们是否喜欢,保存和/或烹饪食谱。此外,当您查看用户的个人资料时,您可以搜索他们喜欢,保存和烹饪的食谱。以及用户创建的食谱。

当前设置有效,但似乎不可扩展,是Recipe的索引带有各种yes / no标志,以及welcome_by_users,saved_by_users和cooked_by_users各一个字段。这些字段包含一组user_id,这些user_id已对配方执行了任何操作。然后,当我想要过滤时,我传递user_id(或者,如果你想看看你的朋友已经烹饪了什么,则传递user_ids)并过滤关于id是否显示在相关数组中的结果。但是,如果最终可能有数以百万计的这些交互,那么这种方式的存储和搜索似乎并不好。我也可以将配方ID存储在用户身上,但最后,似乎我最终会遇到类似的问题,我会更加麻烦地需要首先从用户查询这些ID。

我一直在尝试和/或考虑的事情:

  1. 反正义化一切。我认为这是首选的ES方式,但我担心这只是重复数据(可以搜索食谱标题,内容,类别等),其中一些经常变化。例如,如果用户喜欢食谱,那么更新该食谱的喜欢计数,以便可以按照计数对结果进行排序。
  2. 我认为这需要为曾经与之互动的用户创建配方的副本,然后在那里存储交互。因此,喜欢的标志和已保存的类别的数据数组,以及已经烹饪的数据数组。我相信我仍然需要传递一个user_ids数组来过滤,如果有人过滤了他们的朋友煮过的东西,但我不认为用户会有数百万的朋友,可能不到200岁。这还是许多ID传入?将那么多数据保存到太多数据?此外,有些字段可能会经常更新,这使得这个声音非常糟糕。

    1. 在用户下嵌套食谱也听起来不正确,因为在更新任何其他内容时需要重新编制索引。

    2. 在文档中,父/子听起来像是最后的选择,对于这个用例也听起来不安静。

    3. 我已经考虑过从iSQL中删除id(即用户与之交互过的配方ID)并将其传递给ES。但是,其中一个,mySQL只能连接这么多的id(同样地,不确定在代码中如果它们对于mySQL来说太长,将它们构建成代码中的字符串是否明智),还有两个,我不确定这是不是过滤ES结果的有效方法(数据太多)。

    4. 我已经尝试过其他一些事情,例如分别索引用户和食谱之间的关系,但一切似乎都归结为疯狂的城镇。

      我也不太清楚ES有多少太多了。通过文档阅读,有人提到“如果你有很多XYZ,这不是一个好主意”,但我不知道在这些情况下有多少意味着什么。我读到的唯一具体部分是关于更新非规范化博客帖子中用户的名称,更新“几千”只需不到一秒钟。是否有任何规则我可以​​用来估计存储在字段中的数据有多大,或者传递给过滤器的数据或者要更新的文档?

1 个答案:

答案 0 :(得分:0)

在Elasticsearch上实现这一点非常棘手,因为实体(用户,食谱,类别......)以各种方式链接在一起,并且在没有竞争条件的情况下以高吞吐量更新这些数据并非易事。

用户之间是否共享类别?我的意思是当食谱保存到类别(如标记)时,每个人都可以看到这些信息吗?如果是这样,这个结构应该让你开始。

听起来你应该有两种类型的文件:食谱和烹饪动作/用户/食谱。

配方结构:

{
  "_id": "rga9gia0934gau90" (could be auto-generated by ES)
  "created_by": 123         (user id)
  "contents": "Pour x grams of sugar..."
  "ingredients": ["sugar", "..."],
  "tags": ["unhealthy", "sweet", "..."]
}

烹饪日期结构:

{
  "_id": "123-rga9gia0934gau90" (generated as {user_id}-{recipe-id})
  "user_id": 123,
  "recipe_id": "rga9gia0934gau90",
  "cooked_at_dates": ["2017-01-02", "2017-01-07"],
  "cooked_n_times": 2
}

这种方式大多数更新都是单个文档的本地更新。然而,诸如“甜食谱用户X还没有烹饪”的一些查询需要两个ES查询:首先获得用户已经烹饪的所有食谱的食谱ID,并且第二查询查找没有任何食谱的所有甜食谱。列出的ids。这不会扩展到成千上万的食谱,但应该可以正常工作数百或数千。