在单个调用中从弹性搜索中获取完整的树

时间:2015-08-11 11:13:12

标签: elasticsearch

我想在弹性搜索中存储员工层次结构。首席财务官,首席技术官,首席运营官等向首席执行官汇报。每个员工都可以拥有自己的报告。

我认为上面可以使用弹性搜索父子关系来完成。我们是否可以编写查询以在一次调用中获取所有报告者(直接报告者和子报告者)。 例如,如果我们查询首席执行官,我们应该让所有员工和首席财务官,我们应该让财务部门的员工。

RDMS中存在类似SQL Server的CTE。

2 个答案:

答案 0 :(得分:4)

ES中的亲子关系是:

  1. 父母对儿童一无所知
  2. 儿童必须提供_parent与其联系并妥善路由。
  3. 父子映射由ES通过内存映射处理。
  4. 父/子文件在任何其他方面都是独立的。
  5. 所以,没有简单的方法(没有办法实际存储任何关系数据的正常形式,因为ES在非关系数据库中)。解决方法:

    • 使用has_parent / has_child查询查询文档(只有1级关系适用于此)
    • 将文档存储为nested个对象(注意,如果任何成员更改,此模型会重新索引整个文档)
    • 非规范化数据(非关系存储的最自然方式,IMO)

答案 1 :(得分:2)

首先,避免以关系数据库的方式考虑ES。 ES不太适合连接/关系,尽管它可以通过父/子关系实现类似的效果。甚至不要考虑可能涉及不确定深度的连接。 CTE可以轻松处理,但并非所有关系数据库都支持CTE AFAIK(MySQL为一体)。

亲子关系比IMMO的价值更大。子文档被路由到父母居住的碎片。在您的树的情况下,所有文档最终将追溯到根文档,这将导致所有文档驻留在单个分片中。树的深度可能非常大(在一个不那么小的组织中超过4或5)。此外,如果您使用此解决方案,根据其ID从ES检索(通过GET API)特定子文档是非常不方便的,因为您必须指定其父ID一直到它的ID根

我认为最好将PATH从根目录存储到但不包括当前员工作为ID列表。因此,每个员工都有一个类似的字段:

"superiors": [CEO_ID, CTO_ID, ... , HER_DIRECT_MANAGER_ID],

因此它完全非规范化,您的应用程序必须为此列表做好准备。

通过此设置,获取员工的所有下属:

  1. 使用过滤器agg或过滤后的查询过滤掉此员工自己的superiors字段中的ID以及自己的ID。
  2. terms字段上执行superiors个攻击,您将拥有该员工的所有下属。
  3. 我必须承认至少需要两个查询。第一个是GET请求检索此员工的superiors字段,然后是第二个查询以执行上述操作。

    另外,不要担心由于非规范化造成的重复。 ES可以处理比您在此处保存的数据更多的数据。