一、背景

在我们工作的过程中,有些时候我们需要用到父子文档的关系映射。**比如:**一个问题有多个答案、一本书籍有多个评论等等。此处我们可以使用 es 的 jion数据类型或 nested来实现。此处我们使用join来建立es中的父子文档关系。

二、需求

我们需要创建一个计划(plan),计划下存在活动(activity)和书籍(book),书籍下存在评论(comments)。

即层级结构为:

     plan
/ \
/ \
activity book
|
|
comments

三、前置知识

  1. 每一个mapping下只能有一个join类型的字段。
  2. 父文档和子文档必须在同一个分片(shard)上。即: 增删改查一个子文档都必须和父文档使用相同的 routing key。
  3. 每个元素只能有一个父,但是可以存在多个子。
  4. 可以为一个已经存在的 join 字段增加新的关联关系。
  5. 可以为一个已经是父的元素增加一个子元素。

join数据类型在elasticsearch中不应该像关系型数据库那种使用。而且has_childhas_parent都是比较消耗性能的。

只有当 子的数据 远远大于 父的数据时,使用join才是有意义的。比如:一个博客下,有多个评论。

四、实现步骤

1、创建 mapping

PUT /plan_index
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"plan_id":{
"type": "keyword"
},
"plan_name":{
"type": "text",
"fields": {
"keyword":{
"type" : "keyword",
"ignore_above" : 256
}
}
},
"act_id":{
"type": "keyword"
},
"act_name":{
"type": "text",
"fields": {
"keyword":{
"type" : "keyword",
"ignore_above" : 256
}
}
},
"comment_id":{
"type": "keyword"
},
"comment_name":{
"type": "text",
"fields": {
"keyword":{
"type" : "keyword",
"ignore_above" : 256
}
}
},
"creator":{
"type": "keyword"
},
"create_time":{
"type": "date",
"format": "yyyy-MM-dd||yyyy-MM-dd HH:mm:ss"
},
"plan_join": {
"type": "join",
"relations": {
"plan": ["activity", "book"],
"book": "comments"
}
}
}
}
}

注意️

2、添加父文档数据

此处添加的是 (plan) 数据。

PUT /plan_index/_doc/plan-001
{
"plan_id": "plan-001",
"plan_name": "四月计划",
"creator": "huan",
"create_time": "2021-04-07 16:27:30",
"plan_join": {
"name": "plan"
}
} PUT /plan_index/_doc/plan-002
{
"plan_id": "plan-002",
"plan_name": "五月计划",
"creator": "huan",
"create_time": "2021-05-07 16:27:30",
"plan_join": "plan"
}

注意️:

1、如果是创建父文档,则需要使用 plan_join 指定父文档的关系的名字(此处为plan)。

2、plan_join为创建索引的 mapping时指定join的字段的名字。

3、指定父文档时,plan_join的这2种写法都可以。

3、添加子文档

PUT /plan_index/_doc/act-001?routing=plan-001
{
"act_id":"act-001",
"act_name":"四月第一个活动",
"creator":"huan.fu",
"plan_join":{
"name":"activity",
"parent":"plan-001"
}
} PUT /plan_index/_doc/book-001?routing=plan-001
{
"book_id":"book-001",
"book_name":"四月读取的第一本书",
"creator":"huan.fu",
"plan_join":{
"name":"book",
"parent":"plan-001"
}
} PUT /plan_index/_doc/book-002?routing=plan-001
{
"book_id":"book-002",
"book_name":"编程珠玑",
"creator":"huan.fu",
"plan_join":{
"name":"book",
"parent":"plan-001"
}
} PUT /plan_index/_doc/book-003?routing=plan-002
{
"book_id":"book-003",
"book_name":"java编程思想",
"creator":"huan.fu",
"plan_join":{
"name":"book",
"parent":"plan-002"
}
} # 理论上 comment 的父文档是 book ,但是此处routing使用 plan 也是可以的。
PUT /plan_index/_doc/comment-001?routing=plan-001
{
"comment_id":"comment-001",
"comment_name":"这本书还可以",
"creator":"huan.fu",
"plan_join":{
"name":"comments",
"parent":"book-001"
}
} PUT /plan_index/_doc/comment-002?routing=plan-001
{
"comment_id":"comment-002",
"comment_name":"值得一读,棒。",
"creator":"huan.fu",
"plan_join":{
"name":"comments",
"parent":"book-001"
}
}

注意️:

1、子文档(子孙文档等)需要和父文档使用相同的路由键。

2、需要指定父文档的id。

3、需要指定join的名字。

4、查询文档

1、根据父文档id查询它下方的子文档

**需求:**返回父文档id是plan-001下的类型为book的所有子文档。

GET /plan_index/_search
{
"query":{
"parent_id": {
"type":"book",
"id":"plan-001"
}
}
}

2、has_child返回满足条件的父文档

**需求:**返回创建者(creator)是huan.fu,并且子文档最少有2个的父文档。

GET /plan_index/_search
{
"query": {
"has_child": {
"type": "book",
"min_children": 2,
"query": {
"match": {
"creator": "huan.fu"
}
}
}
}
}

3、has_parent返回满足父文档的子文档

**需求:**返回父文档(book)的创建者是huan.fu的所有子文档

GET /plan_index/_search
{
"query": {
"has_parent": {
"parent_type": "book",
"query": {
"match": {
"creator":"huan.fu"
}
}
}
}
}

五、Nested Object 和 join 对比

Nested Object join (Parent/Child)
1、文档存储在一起,读取性能高 1、父子文档单独存储,互不影响。但是为了维护join的关系,需要占用额外的内容,读取性能略差。
2、更新父文档或子文档时,需要更新整个文档。 2、父文档和子文档可以单独更新。
3、适用于查询频繁,子文档偶尔更新的情况。 3、适用于更新频繁的情况,且子文档的数量远远超过父文档的数量。

六、参考文档

1、join数据类型

2、has child查询

3、has parent查询

4、parent id查询

elasticsearch父子文档处理(join)的更多相关文章

  1. elasticsearch 父子文档(十一)

    说明 需求 一个产品多个区域销售 每个区域有自己的价格, 方式1冗余行,a 产品分别在  area1 area2 area3区域销售 a产品就会生成3条产品数据 搜索id去重就行了,但是问题就是 聚合 ...

  2. elasticsearch——海量文档高性能索引系统

    elasticsearch elasticsearch是一个高性能高扩展性的索引系统,底层基于apache lucene. 可结合kibana工具进行可视化. 概念: index 索引: 类似SQL中 ...

  3. ES 父子文档查询

    父子文档的特点 1. 父/子文档是完全独立的. 2. 父文档更新不会影响子文档. 3. 子文档更新不会影响父文档或者其它子文档. 父子文档的映射与索引 1. 父子关系 type 的建立必须在索引新建或 ...

  4. elasticsearch 路由文档到分片

    路由文档到分片 当你索引一个文档,它被存储在单独一个主分片上.Elasticsearch是如何知道文档属于哪个分片的呢?当你创建一个新文档,它是如何知道是应该存储在分片1还是分片2上的呢? 进程不能是 ...

  5. ElasticSearch部署文档(Ubuntu 14.04)

    ElasticSearch部署文档(Ubuntu 14.04) 参考链接 https://www.elastic.co/guide/en/elasticsearch/guide/current/hea ...

  6. ElasticSearch——原始文档和倒排索引

    一.原始文档 如上图所示, 第二象限是一份原始文档,有title和content2个字段,字段取值分别为”我是中国人”和” 热爱共X产党”,这一点没什么可解释的.我们把原始文档写入Elasticsea ...

  7. 007-elasticsearch5.4.3【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念

    一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 L ...

  8. Elasticsearch 删除文档

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

  9. Elasticsearch 更新文档

    章节 Elasticsearch 基本概念 Elasticsearch 安装 Elasticsearch 使用集群 Elasticsearch 健康检查 Elasticsearch 列出索引 Elas ...

随机推荐

  1. TCP协议中的TIME_WAIT详细说明

    文章目录 4.3设置TIME_WAIT状态的目的 4.3.1 实现TCP全双工连接的关闭 4.3.2 使过时的重复报文段失效 4.3.3 TIME_WAIT状态的自结束 4.3.4 TIME_WAIT ...

  2. Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!

    前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...

  3. Vue设置全局cookies样式

    ''' 配置全局cookies样式 下载:cnpm install vue-cookies import cookies from 'vue-cookies' Vue.prototype.$cooki ...

  4. 【PHP数据结构】图的遍历:深度优先与广度优先

    在上一篇文章中,我们学习完了图的相关的存储结构,也就是 邻接矩阵 和 邻接表 .它们分别就代表了最典型的 顺序存储 和 链式存储 两种类型.既然数据结构有了,那么我们接下来当然就是学习对这些数据结构的 ...

  5. 使用metaweblog API实现通用博客发布 之 版本控制

    使用metaweblog API实现通用博客发布 之 版本控制 接上一篇本地图片自动上传以及替换路径,继续解决使用API发布博客的版本控制问题. 当本地文档修订更新以后,如何发现版本更新,并自动发布到 ...

  6. 创建一个新的解耦的Orchard Core CMS网站

    引言本文将介绍创建一个功能齐全.解耦的CMS网站的过程,该网站允许您编辑博客帖子并呈现它们.解耦是一种开发模型,其中站点的前端和后端(管理)托管在同一个Web应用程序中,但只有后端由CMS驱动.然后, ...

  7. Jmeter系列(19)- 常用配置文件

    JMeter.properties :跟Jmeter配置相关的配置信息都在这边,比如:Jmeter GUI页面的语言.日志级别设置等 User.properties:用户自定义相关的所有变量,会复写J ...

  8. Vue 初学

    Vue 的基本代码:      概念简介:Vue.js 是目前最火的一个前端框架,只关注视图层,主要负责MVC中的V这一层     MVC 是后端的分层开发概念:     MVVM是前端视图层的概念, ...

  9. 彻底关闭Windows自动更新

    win+r--输入services.msc(服务管理窗口)停止windows update服务并禁用同时在恢复里,改为无操作 win + r --输入gpedit.msc(本地组策略编辑器)家庭版没有 ...

  10. P4338-[ZJOI2018]历史【LCT】

    正题 题目链接:https://www.luogu.com.cn/problem/P4338 题目大意 给出\(n\)个点的一棵树,和每个点进行\(access\)的次数\(a_i\),要求安排一个顺 ...