【问题标题】:How to handle an item being apart of multiple lists in Elasticsearch?如何处理 Elasticsearch 中多个列表中的项目?
【发布时间】:2014-08-06 12:53:10
【问题描述】:

我正在开发一个由 Elasticsearch 索引的文档可以显示在多个列表中的系统。

列表名称:

  • 列表1
  • 列表2
  • 列表3
  • 列表4

被索引的文档:

{ title : 'Title' }

我每秒收到一次这样的文件。一个文档可以出现在多个列表中(一些业务逻辑也决定了该文档属于哪个列表)。我目前的方法是将列表数据附加到文档中,使文档看起来像这样:

{ title : 'Title', lists : ['LIST2', 'LIST4'] }

这种方法使我能够通过简单地查询列表数组包含 LIST2 的文档来列出 LIST2 中的所有文档。它还使我能够在 LIST2 中搜索文档。

客户提出了一个新要求,即 LISTS 必须是可合并的。这意味着用户可以将 LIST3 合并到 LIST2 中,这实质上意味着:

  • 更新所有附有 LIST3 列表的文档并将其更改为 LIST2
  • 删除 LIST2。

我的问题:在 Elasticsearch 中有没有更好的方法来处理这个问题?这种方法的可扩展性如何?我认为的问题领域可能是:

  1. 未来会有很多 LISTS(可能是一百万)。帖子所属的 LISTS 越多,文档列表数组就越大。 Elasticsearch 在这个部门的表现如何?
  2. 合并列表似乎是一项非常昂贵的操作。

【问题讨论】:

  • 一个示例文档(json)会更有帮助。
  • 我还有很多字段,但我已经去掉了它们。这是文档的稍微简化的版本:gist.github.com/peeter-tomberg/b285f900095cd89563bf watchlists 是文档所在的列表(mongo ID)数组。
  • 还有,合并是如何发生的?在您的文档中?
  • 目前我们“手动”进行。我们在“列表”中查询所有包含 LIST3 的文档,并将它们全部更新为包含 LIST2。

标签: database-design elasticsearch


【解决方案1】:

我认为答案实际上取决于您愿意放弃什么以换取更大的灵活性。您的解决方案在查询时肯定有优势,但也许您不想花费这么多资源重新索引所有更改?如果是这样,这里的另一个解决方案建议维护一个单独的类型来存储反向关系,其中索引是基于列表的,并且您可以更轻松地更新您的列表。

其中一个陷阱可能是在搜索时失去灵活性。如果您想要列表“A”中每个文档的详细信息,则必须查询“列表”类型,然后针对该列表的所有 docID 运行另一个查询。可能有插件可让您加入查询(使用此特定架构),但您必须进行一些研究。

此外,如果您的列表最终变得非常大(想象一下索引包含一百万个标题的列表文档!),这可能会出现问题。但是话又说回来,如果您必须使用正确的 listID 列表更新一百万个文档,您可能会在解决方案中遇到类似的问题。这取决于您对数据集最终会变得多大的期望,以及在应用解决方案时哪些功能对您最重要。

话虽如此,另一个潜在的解决方案可能是使用父/子文档。父级是列表,子级是文档。这将保持查询灵活性不变,因为您可以针对父项上的鉴别器查询子文档。但是合并将如何工作?如前所述,一切都是有代价的,在这种情况下,我将设计列表以使其具有 2 个 ID 字段。一个是“以前的”列表名称,另一个是可搜索的别名。

例如,您有列表“A”和列表“B”。基本的文档结构类似于 list : { alias: 'A', name: 'A'},对于 B 也是如此。假设有一天,你想将 A 合并到 B。然后你会做的是更新 List文档A,并将'A'的别名设置为'B'。在搜索时,搜索文档时,您将查询类似于“where parent.alias = [list_name]”的查询。此外,出于审核目的,您可以将刚刚被替换的列表名称 ('A') 排队到上一个列表名称字段中。 (这部分完全是可选的.. 取决于你想怎么做)

不幸的是,这意味着您可以拥有许多具有相同别名的列表类型(并且还占用更多内存),但这会阻止大规模重新索引(在任一规模上),并且您在搜索时会受到很小的性能影响支持父/子关系(文档将在搜索时共享相同的分片,但不会像嵌套文档那样共享相同的片段)。

【讨论】:

    【解决方案2】:

    您可以将列表对象作为它们自己的类型进行索引,例如,列表本身只有一个属于该列表的文档 ID 列表。然后,当您需要根据文档所属的列表查询文档时,您可以使用术语查找过滤器(一种“连接”)-http://www.elasticsearch.org/blog/terms-filter-lookup/

    没有必要进行两个单独的查询 - 术语查找内置在 elasticsearch 中,可以完全执行需要通过不同文档类型检查成员资格的查询(即“查找” - 与连接或“在哪里”)。您不仅不需要执行两个单独的查询,而且在 elasticsearch 端还有缓存,这使得它非常高效。

    这样可以更轻松地管理列表成员,因为您只需更新 ONE 文档(列表文档)即可合并列表,但在根据列表成员搜索特定文档时,您仍然可以根据需要查询信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      相关资源
      最近更新 更多