ES 笔记四十三:文档的父子关系

Parent / Child

  • 对象和 Nested 对象的局限性
    • 每次更新,需要重新索引整个对象(包括跟对象和嵌套对象)
  • ES 提供了类似关系型数据库中Join 的实现。使用Join数据类型实现,可以通过Parent / Child 的关系,从而分离两个对象
    • 父文档和子文档是两个独立的文档
    • 更新父文档无需重新索引整个子文档。子文档被新增,更改和删除也不会影响到父文档和其他子文档。

父子关系

  • 定义父子关系的几个步骤
    • 设置索引的Mapping
    • 索引父文档
    • 索引子文档
    • 按需查询文档

设置Mapping

ES笔记四十二:文档的父子关系

DELETE my_blogs
# 设定 Parent/Child Mapping
PUT my_blogs
{
  "settings": {
    "number_of_shards": 2
  },
  "mappings": {
    "properties": {
      "blog_comments_relation": {
        "type": "join",
        "relations": {
          "blog": "comment"
        }
      },
      "content": {
        "type": "text"
      },
      "title": {
        "type": "keyword"
      }
    }
  }
}

索引父文档

ES笔记四十二:文档的父子关系

PUT my_blogs/_doc/blog1
{
  "title":"Learning Elasticsearch",
  "content":"learning ELK @ geektime",
  "blog_comments_relation":{
    "name":"blog"
  }
}

PUT my_blogs/_doc/blog2
{
  "title":"Learning Hadoop",
  "content":"learning Hadoop",
    "blog_comments_relation":{
    "name":"blog"
  }
}

索引子文档

  • 父文档和子文档必须存在相同的分片上
    • 确保查询 join 的性能
  • 当指定文档时候,必须指定它的父文档ID
    • 使用route参数来保证,分配到相同的分片

ES笔记四十二:文档的父子关系

#索引子文档
PUT my_blogs/_doc/comment1?routing=blog1
{
  "comment":"I am learning ELK",
  "username":"Jack",
  "blog_comments_relation":{
    "name":"comment",
    "parent":"blog1"
  }
}

PUT my_blogs/_doc/comment2?routing=blog2
{
  "comment":"I like Hadoop!!!!!",
  "username":"Jack",
  "blog_comments_relation":{
    "name":"comment",
    "parent":"blog2"
  }
}

PUT my_blogs/_doc/comment3?routing=blog2
{
  "comment":"Hello Hadoop",
  "username":"Bob",
  "blog_comments_relation":{
    "name":"comment",
    "parent":"blog2"
  }
}

Parent / Child 所支持的查询

  • 查询所有文档
  • Parent Id 查询
  • Has Child 查询
  • Has Parent 查询
    # 查询所有文档
    POST my_blogs/_search
    {}
    #根据父文档ID查看
    GET my_blogs/_doc/blog2
    # Parent Id 查询
    POST my_blogs/_search
    {
    "query": {
    "parent_id": {
      "type": "comment",
      "id": "blog2"
    }
    }
    }
    # Has Child 查询,返回父文档
    POST my_blogs/_search
    {
    "query": {
    "has_child": {
      "type": "comment",
      "query" : {
                "match": {
                    "username" : "Jack"
                }
            }
    }
    }
    }
    # Has Parent 查询,返回相关的子文档
    POST my_blogs/_search
    {
    "query": {
    "has_parent": {
      "parent_type": "blog",
      "query" : {
                "match": {
                    "title" : "Learning Hadoop"
                }
            }
    }
    }
    }

    使用 has_child 查询

  • 返回父文档
  • 通过对子文档进行查询
    • 返回具体相关子文档的父文档
    • 父子文档在相同的分片上,因此Join 效率高

ES笔记四十二:文档的父子关系

使用 has_parent 查询

  • 返回相关性的子文档
  • 通过对父文档进行查询
    • 返回相关的子文档

ES笔记四十二:文档的父子关系

使用 parent_id 查询

  • 返回所有相关子文档
  • 通过对付文档Id 进行查询
    • 返回所有相关的子文档

ES笔记四十二:文档的父子关系

访问子文档

  • 需指定父文档 routing 参数

ES笔记四十二:文档的父子关系

#通过ID ,访问子文档
GET my_blogs/_doc/comment2
#通过ID和routing ,访问子文档
GET my_blogs/_doc/comment3?routing=blog2

更新子文档

  • 更新子文档不会影响到父文档

ES笔记四十二:文档的父子关系


#更新子文档
PUT my_blogs/_doc/comment3?routing=blog2
{
    "comment": "Hello Hadoop??",
    "blog_comments_relation": {
      "name": "comment",
      "parent": "blog2"
    }
}

嵌套对象 v.s 父子文档

Nested Object Parent / Child
优点 文档存储在一起,读取性能高 父子文档可以独立更新
缺点 更新嵌套的子文档时,需要更新整个文档 需要额外的内存去维护关系。读取性能相对差
适用场景 子文档偶尔更新,以查询为主 子文档更新频繁
本作品采用《CC 协议》,转载必须注明作者和本文链接

快乐就是解决一个又一个的问题!

CrazyZard
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!