0%

ElasticSearch-文档的父子关系

对象和 Nested 对象具有每次更新,需要重新索引整个对象(包括根对象和嵌套对象)的局限性。ES 提供了类似关系型数据库中 join 的实现。使⽤ join 数据类型实现,可以通过维护 Parent / Child 的关系,从⽽分离两个对象,满足:

  • ⽗⽂档和⼦⽂档是两个独⽴的⽂档
  • 更新⽗⽂档⽆需重新索引⼦⽂档。⼦⽂档被添加,更新或者删除也不会影响到⽗⽂档和其他的⼦⽂档

1. 父子关系

定义⽗⼦关系的⼏个步骤:

  1. 设置索引的 Mapping
  2. 索引⽗⽂档
  3. 索引⼦⽂档
  4. 按需查询⽂档

首先则是定义索引的 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
2
3
4
POST my_blogs/_search
{

}

其中父子结构文档会按照如下形式进行返回,我们通过响应区分父子文档信息:

2.2 has_child 查询

has_child 查询会返回父文档信息。通过对⼦⽂档进⾏查询来返回具有相关⼦⽂档的⽗⽂档,例如下面查询子文档 usernameJack 的所有父文档信息:

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
2
3
4
5
6
7
8
PUT my_blogs/_doc/comment2?routing=blog2
{
"comment": "I like Hadoop??",
"blog_comments_relation": {
"name": "comment",
"parent": "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

------ 本文结束------