Elasticsearch-文档的父子关系

目录

Parent/Child

父子关系

定义父子关系的几个步骤---

  设置索引的Mapping

  索引父文档

  索引子文档

按需查询文档

根据父文档id查看

parent_id查询

has child查询

has parent

通过子文档id和routing访问子文档 

更新子文档的属性

更新子文档的父文档 

children聚集 

parent聚集

嵌套对象VS父子文档


Parent/Child

  • 对象和Nested对象的局限性

    • 每次更新,需要更新索引整个对象(包括根对象和嵌套对象)

  • ES提供了类似关系型数据库中Join的实现,使用Join数据类型实现,可以通过维护Parent和Child的关系,从而分离两个对象

    • 父文档和子文档是两个独立的文档

    • 更新父文档无需重新索引子文档,子文档添加,更新或者删除也不会影响到父文档和其他子文档

父子关系

定义父子关系的几个步骤---

  设置索引的Mapping

PUT my_blogs
{
  "mappings": {
    "properties": {
      "blog_comments_relation":{
        "type": "join",
        "relations":{
          "blog":"comment"
        }
      },
      "content":{
        "type": "text"
      },
      "title":{
        "type": "keyword"
      }
    }
  }

  索引父文档

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


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

  索引子文档

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

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"
  }
}

按需查询文档

根据父文档id查看(只可以看到父文档的相关信息)

 #根据父文档id查看(只可以看到父文档的相关信息)
GET my_blogs/_doc/blog2

parent_id查询

parent_id查询与has_parent查询的作用相似,都是根据父文档检索子文档。 不同的是,has_parent可以通过query参数设置不同的查询条件;而parent_id查询则只能通过父文档id做检索。例如,查询id为1的子文档:

 #通过parent_id查询对应的子文档
POST my_blogs/_search
{
  "query":{
    "parent_id":{
      "type":"comment",
      "id":"blog2"
    }
  }
}

has child查询

has_child查询是根据子文档检索父文档的一种方法,它先根据查询条件将满足条件的子文档检索出来,在最终的结果中会返回具有这些子文档的父文档。

 #has child查询返回父文档
POST my_blogs/_search
{
  "query":{
    "has_child":{
      "type":"comment",
      "query": {
        "match": {
          "username": "jack"
        }
      }
    }
  }
}

 has parent

has_parent查询与has_child查询正好相反,是通过父文档检索子文档的一种方法。在执行流程上,has_parent查询先将满足查询条件的父文档检索出来,但在最终返回的结果中展示的是具有这些父文档的子文档

#has parent查询返回子文档
POST my_blogs/_search
{
  "query":{
    "has_parent":{
      "parent_type":"blog",
      "query": {
        "match": {
          "title": "Learning Hadoop"
        }
      }
    }
  }
}

通过子文档id和routing访问子文档 

#通过子文档id和routing访问子文档
GET my_blogs/_doc/comment1?routing=blog1 

  更新子文档的属性

 #更新子文档的属性comment
POST my_blogs/_doc/comment3?routing=blog2
{
  "comment":"Hello Hadoop?????",
  "username" : "Bob",
    "blog_comments_relation" : {
      "name" : "comment",
      "parent" : "blog2"
    }
}

 

更新子文档的父文档 

#更新子文档的父文档
POST my_blogs/_doc/comment3?routing=blog2
{
  "comment":"Hello Hadoop!!!!!",
  "username" : "Bob",
    "blog_comments_relation" : {
      "name" : "comment",
      "parent" : "blog1"
    }

children聚集 

如果想通过父文档检索与其关联的所有子文档就可以使用children聚集

POST /my_blogs/_search?filter_path=aggregations
{
  "query":{
    "term": {
      "title": "Hadoop"
    }
  },
  "aggs": {
    "who_is_children": {
      "children": {
        "type": "comment"
      },
      "aggs": {
        "username": {
          "terms": {
            "field": "username.keyword",
            "size": 10
          }
        }
      }
    }
  }
}

在示例中,query参数设置了父文档的查询条件,即名称字段title为hadoop的文档,而聚集查询who_is_children中则使用了children聚集将它的子文档检索出来,同时还使用了一个嵌套聚集username将子文档username字段的词项全部展示出来了

parent聚集

POST /my_blogs/_search?filter_path=aggregations
{
  "query":{
    "match": {
      "comment": "Hadoop"
    }
  },
  "aggs": {
    "who_is_parent": {
      "parent": {
        "type": "comment"
      },
      "aggs": {
        "manager_name": {
          "terms": {
            "field": "title",
            "size": 10
          }
        }
      }
    }
  }
}

//

parent聚集与children聚集正好相反,它是根据子文档查找父文档,parent聚集在Elasrticsearch版本6.6以后才支持。例如通过 "comment"字段为: "Hadoop"的文档,在找该文档的父文档

嵌套对象VS父子文档

Nested ObjectParent/Child
优点文档存储在一起,读取性能高父子文档可以独立更新
缺点更新嵌套的子文档时,需要更新整个文档需要额外的内存维护关系,读取性能相对较差
使用场景子文档偶尔更新,以查询为主子文档更新频繁
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值