elasticsearch,Database Design,elasticsearch" /> elasticsearch,Database Design,elasticsearch" />

Database design 如何在Elasticsearch中处理多个列表中的项目?

Database design 如何在Elasticsearch中处理多个列表中的项目?,database-design,elasticsearch,Database Design,elasticsearch,我正在开发一个系统,通过Elasticsearch索引的文档可以显示在多个列表中 名单名称: 清单1 清单2 清单3 清单4 正在编制索引的文档: { title : 'Title' } 我每秒收到一次这样的文件。一个文档可以出现在多个列表中(一些业务逻辑也决定了文档所属的列表)。我当前的方法是将列表数据附加到文档中,使文档看起来像这样: { title : 'Title', lists : ['LIST2', 'LIST4'] } 这种方法使我能够通过简单地查询列表数组包含LIST2的

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

名单名称:

  • 清单1
  • 清单2
  • 清单3
  • 清单4
正在编制索引的文档:

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

{ title : 'Title', lists : ['LIST2', 'LIST4'] }
这种方法使我能够通过简单地查询列表数组包含LIST2的文档来列出LIST2中的所有文档。它还使我能够在列表2中搜索文档

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

  • 更新所有附加了LIST3列表的文档,并将其更改为LIST2
  • 删除清单2
我的问题:在Elasticsearch中是否有更好的方法处理此问题?这种方法的可扩展性如何?我认为问题可能是:

  • 未来有很多名单(可能是一百万)。帖子所包含的列表越多,文档列表数组就越大。Elasticsearch在这个部门的表现如何
  • 合并列表似乎是一项非常昂贵的操作
    您可以将列表对象作为其自己的类型进行索引,例如,列表本身只有一个属于该列表的文档ID列表。然后,当您需要根据文档所属的列表查询文档时,可以使用术语查找过滤器(排序的“联接”)

    无需执行两个单独的查询——elasticsearch内置了术语查找功能,以执行需要通过不同文档类型检查成员资格的查询(即“查找”——完全类似于联接或“where in”)。您不仅不需要执行两个单独的查询,而且elasticsearch端也有缓存,这使得它非常高效


    这使得管理列表成员身份更加容易,因为您只需更新一个文档(列表文档)即可合并列表,但是,在根据列表成员资格搜索特定文档时,您仍然可以根据需要查询信息。

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

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

    此外,如果你的列表最终变得非常大,这可能会产生问题(想象一下为一个有一百万个标题的列表文档编制索引!)。但是,如果您必须使用正确的列表ID更新一百万个文档,那么您的解决方案中可能会遇到类似的问题。这取决于您对数据集最终会变得多大的期望,以及在应用解决方案时哪些功能对您最重要

    话虽如此,另一个潜在的解决方案可能是使用父/子文档。父对象是列表,子对象是文档。这将保持查询灵活性不变,因为您可以根据父文档上的鉴别器查询子文档。但合并如何运作呢?如前所述,一切都要付出代价,在本例中,我将设计列表,使其具有2个ID字段。一个是“先前”列表名,另一个是可搜索别名

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


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

    一个示例文档(json)将更有帮助。我有更多的字段,但我已经去掉了它们。下面是一个稍微简化的文档版本:监视列表是列表数组(mongo ID)文档在中。在您的文档中,合并是如何对occour说的?目前我们“手动”进行合并。我们查询“列表”中包含列表3的所有文档,并更新所有文档以包含列表2。