对象和 Nested 对象具有每次更新,需要重新索引整个对象(包括根对象和嵌套对象)的局限性。ES 提供了类似关系型数据库中 join 的实现。使⽤ join 数据类型实现,可以通过维护 Parent / Child 的关系,从⽽分离两个对象,满足:
1. 父子关系
定义⽗⼦关系的⼏个步骤:
- 设置索引的 Mapping
- 索引⽗⽂档
- 索引⼦⽂档
- 按需查询⽂档
首先则是定义索引的 mapping 信息,示例如下:
接着便是索引父文档,查看下图索引两个文档 blog1 和 blog2,blog_coments_relatuion.name
指明值 blog
即是声明其为父文档,blog_coments_relatuion
在 mapping 已经定义:
然后则是索引子文档,观察下图。comment1
为子文档 ID,而其后的 routing=blog1
用于确保子文档和父文档 blog1 能够索引到相同的分片上,以确保查询 join 的性能。另外则是通过 blog_coments_relatuion.name
指定值 blog1
来将该子文档关联到对应的父文档 blog1 上。
最后我们便能按照需要查询⽂档。
2. Parent / Child 查询
Parent / Child ⽀持如下不同方式的查询:
- 查询所有⽂档
- Parent Id 查询
- Has Child 查询
- Has Parent 查询
2.1 查询所有文档
同普通查询所有文档一样,可以采用如下 DSL 检索获取所有文档。
1 | POST my_blogs/_search |
其中父子结构文档会按照如下形式进行返回,我们通过响应区分父子文档信息:
2.2 has_child 查询
has_child 查询会返回父文档信息。通过对⼦⽂档进⾏查询来返回具有相关⼦⽂档的⽗⽂档,例如下面查询子文档 username
为 Jack
的所有父文档信息:
2.3 has_parent 查询
与 has_child 查询相反,has_parent 查询会返回相关的⼦⽂档,即通过对⽗⽂档进⾏查询返回所有相关⼦⽂档。例如查询父文档标题 title 为 Learning Hadoop
的所有子文档:
2.4 parent_id 查询
通过指定 parent_id 可以查询获取其下面的所有相关⼦⽂档,例如:
2.5 查看父子文档
可以根据父文档 ID 查看父文档:
1 | GET my_blogs/_doc/blog2 |
而查看子文档则比较特殊,需要以如下形式进行查询,即指明 routing
:
1 | GET my_blogs/_doc/comment2?routing=blog2 |
2.6 更新子文档
更新⼦⽂档不会影响到⽗⽂档,可以参考如下示例对子文档进行更新:
1 | PUT my_blogs/_doc/comment2?routing=blog2 |
3. 对比嵌套对象
相关阅读:
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-has-child-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-has-parent-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-parent-id-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-parent-id-query.html