我正在开发一个系统,其中由Elasticsearch索引的文档可以显示在多个列表中。
列表名称:
正在编入索引的文件:
{ title : 'Title' }
我每秒都会收到这样的文件。文档可以出现在多个列表中(某些业务逻辑也确定文档所属的列表)。我目前的方法是将列表数据附加到文档中,因此文档看起来像这样:
{ title : 'Title', lists : ['LIST2', 'LIST4'] }
这种方法使我能够通过查询列表数组包含LIST2的文档来列出LIST2中的所有文档。它还使我能够在LIST2中搜索文档。
客户认为LISTS需要合并的新要求。这意味着用户可以将LIST3合并到LIST2中,这实际上意味着:
我的问题:在Elasticsearch中有更好的方法来解决这个问题吗?这种方法的可扩展性如何?我认为的问题可能是:
答案 0 :(得分:0)
您可以将列表对象编入索引作为自己的类型,其中列表本身例如只包含属于该列表的文档ID列表。然后,当您需要根据文档所属的列表查询文档时,可以使用术语查找过滤器(排序的“连接”) - http://www.elasticsearch.org/blog/terms-filter-lookup/。
没有必要进行两个单独的查询 - 在弹性搜索中内置术语查找,以完成那种需要通过不同文档类型检查成员资格的查询(即“查找” - 完全类似于连接或“在哪里”)。你不仅不需要做两个单独的查询,而且还有弹性搜索方面的缓存,这使得它非常有效。
这样可以更轻松地管理列表成员资格,因为您只需要更新一个文档(列表文档)来合并列表,但在根据列表成员资格搜索特定文档时,您仍然可以根据需要查询信息。
答案 1 :(得分:0)
我认为答案实际上取决于你愿意放弃的东西以换取更大的灵活性。您的解决方案在查询时肯定具有优势,但您可能不希望花费这么多资源重新索引所有更改?如果是这样,其他解决方案建议维护一个单独的类型,以反向存储关系,其中索引是基于列表的,并且您可以更轻松地更新列表。
这样做的一个缺陷可能是在搜索时失去灵活性。如果您需要列表“A”中每个文档的详细信息,则必须查询“列表”类型,然后针对该列表的所有docID运行另一个查询。可能有插件允许您加入查询(使用此特定架构),但您必须进行一些研究。
此外,如果您的列表最终变得非常大,这可能会出现问题(想象一下将列表文档索引为一百万个标题!)。但是,如果您必须使用正确的listID列表更新一百万个文档,那么您可能会在解决方案中遇到类似的问题。这取决于您对数据集最终变得多大的期望,以及在应用解决方案时哪些功能对您最重要。
话虽如此,另一个可能的解决方案可能是使用父/子文件。父母将是列表,孩子将是文件。这将保持查询灵活性不变,因为您可以查询父文件中的歧视器的子文档。但合并将如何运作?如上所述,所有内容都有成本,在这种情况下,我会设计列表,使其具有2个ID字段。一个人将保留“先前”列表名称,另一个将是可搜索别名。
例如,您有列表'A'和列表'B'。基本文档结构类似于list:{alias:'A',name:'A'},同样适用于B.有一天,你想将A合并到B.你要做的是,更新列表文档A,并将'A'的别名设置为'B'。在搜索时,搜索文档时,您将查询类似“where parent.alias = [list_name]”的内容。此外,出于审计目的,您可以将刚被替换的列表名称(“A”)排队到上一个列表名称字段中。 (这部分完全是可选的......直到你想怎么做)
不幸的是,这意味着您可以拥有多个具有相同别名的列表类型(并且还会占用更多内存),但这可以防止大量重新编制索引(在任何规模上),并且您在搜索时获得较小的性能影响支持父/子关系(文档将在搜索时共享相同的分片,但不与嵌套文档共享相同的分段)。