父-子关系文档 在实质上类似于 nested model :允许将一个对象实体和另外一个对象实体关联起来。而这两种类型的主要区别是:在 nested
objects 文档中,所有对象都是在同一个文档中,而在父-子关系文档中,父对象和子对象都是完全独立的文档。
父-子关系的主要作用是允许把一个 type 的文档和另外一个 type 的文档关联起来,构成一对多的关系:一个父文档可以对应多个子文档 。与 nested
objects 相比,父-子关系的主要优势有:
-
更新父文档时,不会重新索引子文档。
-
创建,修改或删除子文档时,不会影响父文档或其他子文档。这一点在这种场景下尤其有用:子文档数量较多,并且子文档创建和修改的频率高时。
-
子文档可以作为搜索结果独立返回。
Elasticsearch 维护了一个父文档和子文档的映射关系,得益于这个映射,父-子文档关联查询操作非常快。但是这个映射也对父-子文档关系有个限制条件:父文档和其所有子文档,都必须要存储在同一个分片中。
父-子文档ID映射存储在 [docvalues] 中。当映射完全在内存中时, [docvalues] 提供对映射的快速处理能力,另一方面当映射非常大时,可以通过溢出到磁盘提供足够的扩展能力
建立父-子文档映射关系时只需要指定某一个文档 type 是另一个文档 type 的父亲。 该关系可以在如下两个时间点设置:1)创建索引时;2)在子文档 type 创建之前更新父文档的 mapping。
举例说明,有一个公司在多个城市有分公司,并且每一个分公司下面都有很多员工。有这样的需求:按照分公司、员工的维度去搜索,并且把员工和他们工作的分公司联系起来。针对该需求,用嵌套模型是无法实现的。当然,如果使用 application-side-joins 或者 data denormalization 也是可以实现的,但是为了演示的目的,在这里我们使用父-子文档。
我们需要告诉Elasticsearch,在创建员工 employee
文档 type 时,指定分公司 branch
的文档 type 为其父亲。
PUT /company
{
"mappings": {
"branch": {},
"employee": {
"_parent": {
"type": "branch" (1)
}
}
}
}
-
employee
文档 是branch
文档的子文档。