ElasticSearch 中的Parent-Child关系和nested模型是相似的, 两个都可以用于复杂的数据结构中,区别是 nested 类型的文档是把所有的实体聚合到一个文档中而Parent-Child现对于比较独立,每个实体即为一个文档
Parent-Child 优点
1、父文档更新时不用重新为子文档建立索引
2、子文档的增加、修改、删除是对父文档和其他子文档没有任何影响的,这非常适用于子文档非常大并且跟新频繁的场景
3、子文档也可以查询结果返回
ElasticSearch 内部维护一个map来保存Parent-Child之间的关系,正是由于这个map,所以关联查询能够做到响应速度很快,但是确实有个限制是Parent 文档和所有的Child 文档都必须保存到同一个shard中
ElasticSearch parent-child ID的映射是存到Doc value 中的,有足够的内存时响 应是很快的。当这个map很大的时候,还是有要有一部分存储在硬盘中的。

Parent-Child Mapping

为了建立Parent-Child 模型我们需要在创建mapping的时候指定父文档和子文档或者在子文档创建之前利用update-index API 来指定
例如:我们有个公司,其子公司分布在全国各地,我要分析员工和子公司的关系
我们使用Parent-Child 机构
我们需要建立employee type 和 branch type 并且指定 branch 为_parent

PUT /company
{"mappings": {"branch": {},"employee": {"_parent": {"type": "branch"}}}
}

Indexing Parents and Children

创建父索引和创建其他索引并没有区别,父文档并不需要知道他们的子文档

POST /company/branch/_bulk
{ "index": { "_id": "london" }}
{ "name": "London Westminster", "city": "London", "country": "UK" }
{ "index": { "_id": "liverpool" }}
{ "name": "Liverpool Central", "city": "Liverpool", "country": "UK" }
{ "index": { "_id": "paris" }}
{ "name": "Champs Élysées", "city": "Paris", "country": "France" }

创建子文档的时候你必须指出他们的父文档的id

PUT /company/employee/1?parent=london
{"name":  "Alice Smith","dob":   "1970-10-24","hobby": "hiking"
}

指定parent id 有两个目的:他是父文档和子文档的关联,而且他也保证了父文档和子文档会存储在同一个shard中,
在routing那个章节我们解释了ElasticSearch 如何利用routing的值来决定分配到shard中的,如果文档没有指定routing的值的化,那么默认为_id,公式为

shard = hash(routing) % number_of_primary_shards

但是,如果指定了 parent id 那么routing的值就不是_id 了 而是 parent id,换句话说就是父文档和子文档是具有相同的routing的值来确保他们会分配到同一个shard中的
当我们用GET请求来检索子文档时,我们需要指定parent id,并且创建索引、更新索引、还有删除索引都需要指定parent id,不像搜索的请求,他会分发到所有的shard中,这些single-document请求只会发送到存储它的shard中。如果没有指定parent id 也许请求会发送到一个错误的shard中
当我们使用buk API 时也需要指定parent id

POST /company/employee/_bulk
{ "index": { "_id": 2, "parent": "london" }}
{ "name": "Mark Thomas", "dob": "1982-05-16", "hobby": "diving" }
{ "index": { "_id": 3, "parent": "liverpool" }}
{ "name": "Barry Smith", "dob": "1979-04-01", "hobby": "hiking" }
{ "index": { "_id": 4, "parent": "paris" }}
{ "name": "Adrien Grand", "dob": "1987-05-11", "hobby": "horses" }

Finding Parents by Their Children

has_child 和 filter 可以根据子文档的内容来查询父文档,例如我们可以用这样的语句搜索所有分公司,出生在1980年以后的员工:

GET /company/branch/_search
{"query": {"has_child": {"type": "employee","query": {"range": {"dob": {"gte": "1980-01-01"}}}}}
}

has_child 查询会匹配到多个子文档,每个文档都会有不同的关联得分。这些得分如何减少父文档的单个得分取决于分数模型的参数。默认参数为none,即会忽略子文档的得分,并且父文档会加1.0.
下面的查询会同时返回london 还有 liverpool 但是london 会得到一个更好的得分,因为Alice Smith 更加匹配london

GET /company/branch/_search
{"query": {"has_child": {"type":       "employee","score_mode": "max","query": {"match": {"name": "Alice Smith"}}}}
}

min_children and max_children

has_child 和 filter 都有min_children 和 max_children 两个参数,作用是返回那些具有子文档个数与之相匹配的父文档数据
下面的查询会返回具有两个员工以上的分公司

GET /company/branch/_search
{"query": {"has_child": {"type":         "employee","min_children": 2, "query": {"match_all": {}}}}
}

Finding Children by Their Parents

和nested 查询只能返回根节点数据不同的是,父文档和子文档都是相对独立的,并且可以被单独查询,has_child 查询可以根据子文档返回父文档 而 has_parent查询会根据父文档返回子文档
和has_child 查询很相似,下面的查询会返回那些工作在uk的员工

GET /company/employee/_search
{"query": {"has_parent": {"type": "branch", "query": {"match": {"country": "UK"}}}}
}

has_parent 查询也支持score_mode模式,但是它只有两种设置none(默认)和score,每个子文档可以只拥有一个父文档,所以就没有必要将分数分给多个子文档了,这仅仅取决于你使用none还是score模式了

Children Aggregation

Parent-child 支持children aggregation parent aggregation 是不支持的
下面的例子示范了我们分析了员工的兴趣

GET /company/branch/_search
{"size" : 0,"aggs": {"country": {"terms": { "field": "country"},"aggs": {"employees": {"children": { "type": "employee"},"aggs": {"hobby": {"terms": { "field": "hobby"}}}}}}}
}

Grandparents and Grandchildren

parent-child 关系不仅仅可以有两代,他可以具有多代关系,但是所有关联的数据都必须分到同一个shard中去。
我们稍微修改下之前的列子,叫county 成为branch 的父文档

PUT /company
{"mappings": {"country": {},"branch": {"_parent": {"type": "country" }},"employee": {"_parent": {"type": "branch" }}}
}

Countries and branches 只是简单的父子关系,所以我们用相同的方式来创建索引数据

POST /company/country/_bulk
{ "index": { "_id": "uk" }}
{ "name": "UK" }
{ "index": { "_id": "france" }}
{ "name": "France" }POST /company/branch/_bulk
{ "index": { "_id": "london", "parent": "uk" }}
{ "name": "London Westmintster" }
{ "index": { "_id": "liverpool", "parent": "uk" }}
{ "name": "Liverpool Central" }
{ "index": { "_id": "paris", "parent": "france" }}
{ "name": "Champs Élysées" }

parent id 保证了每个branch和他们的父文档都被分配到了同一个shard中了,
如果和之前一样,我们来创建employee 数据,会发生什么?

PUT /company/employee/1?parent=london
{"name":  "Alice Smith","dob":   "1970-10-24","hobby": "hiking"
}

shard 会根据文档的parent ID—london 来分配employee 文档,但是这个london 文档会根据他的parent id uk来分配,所以employee文档和country、branch 很有可能被分配到不同的shard中。
所以我们需要一个额外的参数routing保证所有关联的文档被分配到同一个shard中。

PUT /company/employee/1?parent=london&routing=uk
{"name":  "Alice Smith","dob":   "1970-10-24","hobby": "hiking"
}

parent 参数仍然用于子文档和父文档的关联,routing 参数是用于保证文档被分配到哪个shard中去
查询和聚合对于多级的文档也仍然有效,例如:问了找到哪些城市的员工喜欢hiking

GET /company/country/_search
{"query": {"has_child": {"type": "branch","query": {"has_child": {"type": "employee","query": {"match": {"hobby": "hiking"}}}}}}
}

elasticsearch 基础 —— Parent-Child 父子关系(5.X老版本)相关推荐

  1. elasticsearch的父子_elasticsearch父子关系(官方)实际使用中的一些建议

    当文档索引性能远比查询性能重要的时候,父子关系是非常有用的,但是它也是有巨大代价的.其查询速度会比同等的嵌套查询慢5到10倍! 全局序号和延迟 父子关系使用了全局序数来加速文档间的联合.不管父子关系映 ...

  2. 【18-业务开发-基础业务-商品模块-分类管理-前后端管理系统的启动-为分类管理表增加数据-Json插件的下载-返回具有层级目录、父子关系结构的数据】

    一.知识回顾 [0.三高商城系统的专题专栏都帮你整理好了,请点击这里!] [1-系统架构演进过程] [2-微服务系统架构需求] [3-高性能.高并发.高可用的三高商城系统项目介绍] [4-Linux云 ...

  3. python logging.getlogger_logging.getLogger与logger的父子关系

    我们用logging.getLogger创建logger,通过logger的名字,我们可以实现不同logger的层次关系,或父子关系. def getLogger(name=None): " ...

  4. Logstash 父子关系 配置

    最近在使用Lostash的过程中遇到了一个问题:在一个log文件里包含两类数据,而且两类数据之间存在父子关系,那如何使用lostash的configuration实现这个需求呢 思路: 首先定义父事件 ...

  5. 白话Elasticsearch60-数据建模实战_Join datatype 父子关系数据建模

    文章目录 概述 官网 示例 概述 继续跟中华石杉老师学习ES,第60篇 课程地址: https://www.roncoo.com/view/55 白话Elasticsearch58-数据建模实战_基于 ...

  6. vue-自主研发非父子关系组件之间通信的问题

    相信很多人都知道解决组件间通信:vuex,今天的主角不是它. element-ui里解决组件间通信的思路:emitter.js ,但是如果你拿来你会发现它解决的是父子组件之间的通信问题.如果我们通信的 ...

  7. c++现在有一棵合法的二叉树,树的节点都是用数字表示,现在给定这棵树上所有的父子关系,求这棵树的高度

    题目描述 现在有一棵合法的二叉树,树的节点都是用数字表示,现在给定这棵树上所有的父子关系,求这棵树的高度 输入描述: 输入的第一行表示节点的个数n(1 ≤ n ≤ 1000,节点的编号为0到n-1)组 ...

  8. elasticsearch 基础介绍及使用 (high-level-client)

    目录 一.ElasticSearch 简介 二.ElasticSearch 基础概念 三.SpringBoot 项目引入 ElasticSearch 依赖 1.Maven 引入相关依赖 2.Elast ...

  9. Linux shell 学习笔记(3)— shell 父子关系及内建命令

    1. shell 类型 只要用户登录到某个虚拟控制台终端或是在 GUI 中启动终端仿真器,默认的 shell 程序就会开始运行. 默认的交互 shell 会在用户登录某个虚拟控制台终端或在 GUI 中 ...

  10. 判断类之间的父子关系

    如何判断两个类之间的父子关系? java为我们提供了instanceof运算符,可以用来判断一个对象是否是否个类的实例,所以很容易的想到子类的对象肯定是父类的实例.但是如何所涉及到的类是不可实例化的该 ...

最新文章

  1. webkit入门准备
  2. VMware中为linux设置网络
  3. Ubuntu下使用VSCode的launch.json及tasks.json编写
  4. 【Python】8000字:Python时间系列之datetime模块
  5. ajax请求php返回的数据是整个页面的html,Ajax出错并返回整个页面html的问题
  6. 18春学期《计算机应用基础》,18春学期(1709、1803)《计算机应用基础》在线作业及答案.pdf...
  7. 告别.net ! 2年多了,舍不得!
  8. 网申倒计时4天 | DJI大疆秋招独家笔试攻略
  9. 线程池版本的mysql_MySQL线程池内幕
  10. atitit 项目硬件平台选型attilax总结4blg.docx
  11. 为什么必须在主线程操作UI
  12. 135编辑器点击换图html,135编辑器如何换图片 135编辑器使用教程
  13. eeglab和matlab,Matlab之EEGLAB工具箱脑电数据预处理
  14. graphormer 代码阅读
  15. [luoguP3627][APIO2009]抢掠计划
  16. 场景设计题 汇总 (一)
  17. BootStrap表格鼠标悬停颜色修改
  18. 第一章 TCG 规范科普解读
  19. struct 和 typedef struct 的区别
  20. 上传csv文件后出现乱码

热门文章

  1. Linux上用于Json数据处理并导入Mysql的几个有用Python脚本
  2. 路由器指定局域网dhcp服务器地址,路由器dhcp服务器设置局域网
  3. 【做图工具】MulimgViewer 论文图像处理神器
  4. uln2003驱动蜂鸣器_通过单片机来控制蜂鸣器
  5. Windows 7专业版安装VS2005与WinCE6.0开发环境
  6. ajax帝国cms登录,帝国CMS7.5二次开发之制作Ajax版登陆注册二合一插件(不改系统文件)...
  7. Windows 更新错误 0x80073712
  8. Git clean简介
  9. 仿苹果官网首页面(Hbuilder X+CSS)
  10. 山东网通和电信的DNS