Elasticsearch中的父子关系是单个索引内部文档与文档之间的一种关系,父文档与子文档同属一个索引并通过父文档id建立联系, 类似于关系型数据库中单表内部行与行之间的自关联,比如有层级关系的部门表中记录之间的关联。

join类型

在Elasticsearch中并没有外键的概念,文档之间的父子关系通过给索引定义join类型字段实现。

假设在关系型数据库中有这么一张表employes:

ID name parent
1 tom
2 smith 1
3 john 1

下面用Elasticsearch中的文档来表示这些数据之间的关系。

例如创建一个员工索引employes,定义个join类型的managemet字段用于确定员工之间的管理与被管理关系:

PUT employees
{"mappings": {"properties": {"management": {"type": "join","relations": {"manager": "member"}}}}
}

在示例中,management字段的数据类型被定义为join,同时在该字段的relations参数中定义父子关系为manager与member,其中manager为父而member为子,它们的名称可由用户自定义。文档在父子关系中的地位,是在添加文档时通过join类型字段指定的。

还是以employes索引为例,在向employees索引中添加父文档时,应该将mangement字段设置为manager;而添加子文档时则应该设置为member。具体如下:

PUT /employees/_doc/1
{"name": "tom","management": {"name": "manager"}
}PUT /employees/_doc/2?routing=1
{"name": "smith","management": {"name": "member","parent": "1"}
}PUT /employees/_doc/3?routing=1
{"name": "john","management": {"name": "member","parent": "1"}
}

在示例中,编号为1的文档其management字段通过name参数设置为manager,即在索引定义父子关系中处于父文档的地位,而编号为2的文档既是member,又是management。

在使用父子关系时,要求父子文档必须要映射到同一分片中,所以在添加子文档时routing参数是必须要设置的。显然父子文档在同一分片可以提升在检索时的性能,可在父子关系中使用的查询方法有has_child、has_parent和parent_id查询,还有parent和children两种聚集。

has_child查询

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

例如,如果想检索smith的经理是谁,可以:

POST /employees/_search?filter_path=hits
{"query": {"has_child": {"type": "member","query": {"match": {"name": "smith"}}}}
}
输出结果:
{"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "employees","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"name" : "tom","management" : {"name" : "manager"}}}]}
}

在示例中,has_child查询的type参数需要设置为父子关系中子文档的名称member,这样has_child查询父子关系时就限定在这种类型中检索;query参数则设置了查询子文档的条件,即名称为smith。最终结果会根据smith所在文档,通过member对应的父子关系检索它的父文档。

has_parent查询

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

例如,如果想查看tom的所有下属,可以按示例请求:

POST /employees/_search?filter_path=hits
{"query": {"has_parent": {"parent_type": "manager","query": {"match": {"name": "tom"}}}}
}
输出结果:
{"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "employees","_type" : "_doc","_id" : "2","_score" : 1.0,"_routing" : "1","_source" : {"name" : "smith","management" : {"name" : "member","parent" : "1"}}},{"_index" : "employees","_type" : "_doc","_id" : "3","_score" : 1.0,"_routing" : "1","_source" : {"name" : "john","management" : {"name" : "member","parent" : "1"}}}]}
}

has_parent查询在结构上与has_child查询基本相同,只是在指定父子关系时使用的参数是parent_type而不是type。

parent_id查询

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

例如,查询父文档id为1的子文档:

POST /employees/_search?filter_path=hits
{"query": {"parent_id": {"type": "member","id": 1}}
}
输出结果:
{"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 0.13353139,"hits" : [{"_index" : "employees","_type" : "_doc","_id" : "2","_score" : 0.13353139,"_routing" : "1","_source" : {"name" : "smith","management" : {"name" : "member","parent" : "1"}}},{"_index" : "employees","_type" : "_doc","_id" : "3","_score" : 0.13353139,"_routing" : "1","_source" : {"name" : "john","management" : {"name" : "member","parent" : "1"}}}]}
}

children聚集

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

如果想要查看tom的所有下属就可以按示例的方式检索:

POST /employees/_search?filter_path=aggregations
{"query": {"term": {"name": "tom"}},"aggs": {"members": {"children": {"type": "member"},"aggs": {"member_name": {"terms": {"field": "name.keyword","size": 10}}}}}
}
输出结果:
{"aggregations" : {"members" : {"doc_count" : 2,"member_name" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "john","doc_count" : 1},{"key" : "smith","doc_count" : 1}]}}}
}

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

parent聚集

parent聚集与children聚集正好相反,它是根据子文档查找父文档,parent聚集在Elasrticsearch版本6.6以后才支持。

例如通过name字段为smith的文档,在找该文档的父文档:

POST /employees/_search?filter_path=aggregations
{"query": {"match": {"name": "smith"}},"aggs": {"who_is_manager": {"parent": {"type": "member"},"aggs": {"manager_name": {"terms": {"field": "name.keyword","size": 10}}}}}
}
输出结果:
{"aggregations" : {"who_is_manager" : {"doc_count" : 1,"manager_name" : {"doc_count_error_upper_bound" : 0,"sum_other_doc_count" : 0,"buckets" : [{"key" : "tom","doc_count" : 1}]}}}
}

Elasticsearch文档内部的父子关系相关推荐

  1. mongodb——查询文档内部属性以及数组

    上一篇博客中,我们学会了最基础的查询方法.即按照某一个属性,使用最简单的属性匹配方式查询.这一篇博客中我们来讲一下文档内部嵌套属性的查询以及对于数组的查询. 嵌入文档查询 使用场景:如果一个文档内部有 ...

  2. ElasticSearch 文档的添加、获取、更新、删除_05

    文章目录 新建文档 获取文档 批量获取 文档更新 查询更新 删除文档 批量操作 新建文档 首先新建一个索引. 然后向索引中添加一个文档: PUT blog/_doc/1 {"title&qu ...

  3. elasticsearch文档-modules

    2019独角兽企业重金招聘Python工程师标准>>> modules 模块 cluster 原文 基本概念 cluster: 集群,一个集群通常由很多节点(node)组成  nod ...

  4. Elasticsearch文档CURD操作

    一: 新增文档POST /{index}/{type} 或 PUT /{index}/{type}/{id} 注意:新增文档时可以显式指定id,id可以是数字也可以是字符串,如果不显示指定id,系统会 ...

  5. Elasticsearch文档的CRUD

    索引.类型.文档.字段 索引是ElasticSearch存放数据的地方,可以理解为关系型数据库中的一个数据库. 类型用于区分同一个索引下不同的数据类型,相当于关系型数据库中的表 文档是ElasticS ...

  6. elasticsearch 文档_ElasticSearch系列04:索引与文档的CURD

    引言:上一节我们学习了ES的数据类型,有同学反馈说,里面的语句看不懂.今天,TeHero就为大家讲解ES索引和文档的CURD的操作.掌握了基本操作才能更好的系统学习,让我们开始吧! 1.索引的CURD ...

  7. Elasticsearch 文档内容检索插件 ingest attachment 安装

    Ingest Attachment Processor Plugin 是一个文本抽取插件,本质上是利用了 Elasticsearch的ingest node功能,提供了关键的预处理器 attachme ...

  8. 1.elasticsearch文档存储(保存|修改|删除)

    [README] 0.本文部分内容(数据)总结自 es 开发文档, Document APIs | Elasticsearch Guide [7.2] | Elastic : 1.本文的es版本是7. ...

  9. Elasticsearch文档高级操作

    文章目录 ES条件查询 URL传参查询 请求体传参查询 ES分页查询 ES查询排序 ES多条件查询 同时满足must 部分满足should 范围条件filter ES全文检索 全文检索match 完全 ...

  10. Elasticsearch - 文档分析,IK分词器;文档冲突(十二)

    阅读本文前可先参考 Elasticsearch - Elasticsearch详解:安装部署(一)_MinggeQingchun的博客-CSDN博客 https://blog.csdn.net/Min ...

最新文章

  1. linux删除除某个文件外的其它文件,shell脚本:删除当前目录下除了某几个文件之外的其他文件...
  2. 在Qt4中使用QPersistentModelIndex传递QModelIndex
  3. 在Google Android模拟器中使用SD卡(命令行和eclipse环境)
  4. php使用swoole的应用场景
  5. Boost:双图和boost assign的测试程序
  6. 计算字典的个数_[LeetCode] 440. 字典序的第K小数字
  7. 二,八,十,十六进制之间转换的相应方法
  8. 2018 ios开发者账号同意新协议加联系电话教程
  9. ASP.NET MVC5使用AjaxHelp
  10. Electron 遭封杀,Web 开发者在苹果平台上举步维艰!
  11. C# 判断是否是蜘蛛IP地址
  12. 政企用户网络安全常见风险盘点
  13. 内存条带宽的换算方法以及DDR4内存理论带宽
  14. zabbix报警邮件qq邮箱收不到的问题
  15. grub4dos linux live,grub4dos安装
  16. 凡是能用钱买来的时间就是便宜的;凡是能用时间换来的注意力持续就是有价值的。
  17. 黃綜翰:我的風羽路-新團隊新夢想
  18. Protobuf自动反射消息类型的网络传输方案
  19. GetMessage()用法实例
  20. SpringBoot 实现手机发送短信验证码

热门文章

  1. 互联网发展的四个阶段总结
  2. 笔记本电脑无法进入睡眠状态_小方法解决电脑无法进入睡眠模式问题
  3. 通过雷达图的面积进行总体对比分析是不可靠的!
  4. 请求参数为null问题
  5. HashSet模拟新浪微博用户注册
  6. PS教程:清凉一下美女海报设计教程及素材
  7. conda的environment未被激活解决方案
  8. jvm gc垃圾回收情况
  9. Photoshop 颜色理论(转)
  10. 野火 FireConfig 配置连接Wifi