前言

由于ES6.X版本以后,每个索引下面只支持单一的类型(type),因此不再支持以下形式的父子关系:

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

解决方案:

引入 join datatype

为同一索引中的文档定义父/子关系。

join datatype

join datatype是在同一索引文档中创建父/子关系的特殊字段。该relations部分定义了文档内的一组可能的关系,每个关系是父名和子名。父/子关系可以定义如下:

PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"my_join_field": { ①
"type": "join",
"relations": {
"question": "answer" ②
}
}
}
}
}
}

该字段的名称

定义单个关系,其中answer父级为question

若要用join来索引(动词)文档,必须在文中提供文档的关系名称和可选父文档。例如,下面的示例在question上下文中创建两个父文档:

PUT my_index/_doc/1?refresh
{
"text": "This is a question",
"my_join_field": {
"name": "question" ①
}
} PUT my_index/_doc/2?refresh
{
"text": "This is a another question",
"my_join_field": {
"name": "question"
}
}

本文档是一份question文档

在索引父文档时,可以选择仅指定关系的名称作为快捷方式,而不是将其封装在普通对象符号中:

PUT my_index/_doc/1?refresh
{
"text": "This is a question",
"my_join_field": "question" ①
} PUT my_index/_doc/2?refresh
{
"text": "This is another question",
"my_join_field": "question"
}

父文档的简单表示法只使用关系名称。

索引子文档时,必须在文中添加父级的关系的名称以及文档的父级_source ID

例如,以下示例显示如何索引两个child文档:

PUT my_index/_doc/3?routing=1&refresh
{
"text": "This is an answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
} PUT my_index/_doc/4?routing=1&refresh
{
"text": "This is another answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
}
  • 路由值是强制性的,因为父文件和子文件必须在相同的分片上建立索引。
  • “answer”是此子文档的加入名称。
  • 指定此子文档的父文档ID:1。

Parent-join and performance 父连接和性能

连接字段不应该像关系数据库中的连接那样使用。在弹性搜索中,良好性能的关键是将数据归一化为文档。每个连接字段,HaseBoad或HasyPrad查询对查询性能都会产生显著的影响。

联接字段唯一有意义的情况是,如果数据包含一对多关系,其中一个实体的数量显著超过另一个实体。

Join 类型约束

  1. 每个索引只允许一个Join类型Mapping定义;
  2. 父文档和子文档必须在同一个分片上编入索引;这意味着,当进行删除、更新、查找子文档时候需要提供相同的路由值。
  3. 一个文档可以有多个子文档,但只能有一个父文档。
  4. 可以为已经存在的Join类型添加新的关系。
  5. 当一个文档已经成为父文档后,可以为该文档添加子文档。

Searching with parent-join 使用父连接搜索

父联接创建一个字段,索引文件(中关系的名称my_parentmy_child...)。

它还为每个父/子关系创建一个字段。此字段的名称是join后跟字段#的名称以及关系中父项的名称。因此,例如对于my_parent⇒[ my_childanother_child]关系,该join字段会创建一个名为的附加字段my_join_field#my_parent

_id如果文档是子文件(my_childanother_child),则此字段包含文档链接到的父项,如果文档是_id父项(my_parent),则包含文档链接到的父项。

搜索包含join字段的索引时,始终在搜索响应中返回这两个字段:

GET my_index/_search
{
"query": {
"match_all": {}
},
"sort": ["_id"]
}

将返回:

{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 4,
"max_score": null,
"hits": [
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_score": null,
"_source": {
"text": "This is a question",
"my_join_field": {
"name": "question" ①
}
},
"sort": [
"1"
]
},
{
"_index": "my_index",
"_type": "_doc",
"_id": "2",
"_score": null,
"_source": {
"text": "This is a another question",
"my_join_field": {
"name": "question" ②
}
},
"sort": [
"2"
]
},
{
"_index": "my_index",
"_type": "_doc",
"_id": "3",
"_score": null,
"_routing": "1",
"_source": {
"text": "This is an answer",
"my_join_field": {
"name": "answer", ③
"parent": "1" ④
}
},
"sort": [
"3"
]
},
{
"_index": "my_index",
"_type": "_doc",
"_id": "4",
"_score": null,
"_routing": "1",
"_source": {
"text": "This is another answer",
"my_join_field": {
"name": "answer",
"parent": "1"
}
},
"sort": [
"4"
]
}
]
}
}

此文档属于question join

此文档属于question join

此文档属于answer join

子文档的链接父I​​D

Parent-join queries and aggregations 父连接查询和聚合

有关详细信息,请参阅has_child和 has_parent查询,children聚合和内部命中

join可以在聚合和脚本中访问该字段的值,并可以使用查询 parent_id查询

GET my_index/_search
{
"query": {
"parent_id": {
"type": "answer", ①
"id": "1"
}
},
"aggs": {
"parents": {
"terms": {
"field": "my_join_field#question", ②
"size": 10
}
}
},
"script_fields": {
"parent": {
"script": {
"source": "doc['my_join_field#question']" ③
}
}
}
}

查询parent id字段(另请参阅has_parent查询has_child查询

parent id字段上聚合(也参见children聚合)

访问脚本中的父ID字段

Child-join queries and aggregations 子连接查询和聚合

{
"query": {
"has_child": {
"type": "answer",
"query": {
"match": {
"text": "This is question"
}
}
}
}
} 或 {
"query": {
"has_parent": {
"parent_type": "question",
"query": {
"term": {
"_id": 1
}
},
"inner_hits": { }
}
}
}
{
"took": 42,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"text": "This is a question",
"my_join_field": {
"name": "question"
}
}
}
]
}
}

Global ordinals 全局序数

join字段使用全局序数来加速连接。在对碎片进行任何更改后,需要重建全局序数。父分区值存储在分片中的次数越多,重建join字段的全局序数所需的时间就越长。

默认情况下,全局序数是急切建立的:如果索引发生了变化,该join字段的全局序数将作为刷新的一部分重建。这可以为刷新增加大量时间。但是大多数情况下这是正确的权衡,否则在使用第一个父连接查询或聚合时会重建全局序数。这可能会为您的用户带来显着的延迟峰值,并且通常情况会更糟,因为join 当发生许多写操作时,可能会在单个刷新间隔内尝试重建该字段的多个全局序数。

join字段不经常使用并且频繁发生写入时,禁用预先加载可能是有意义的:

PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": "answer"
},
"eager_global_ordinals": false
}
}
}
}
}

可以按父关系检查全局序数使用的堆量,如下所示:

# Per-index
GET _stats/fielddata?human&fields=my_join_field#question # Per-node per-index
GET _nodes/stats/indices/fielddata?human&fields=my_join_field#question

Multiple children per parent

PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": ["answer", "comment"]
}
}
}
}
}
}

questionanswer和comment的父级

Multiple levels of parent join 多级父级联接

不建议使用多级关系来复制关系模型。每个级别的关系在查询时在内存和计算方面增加了开销。如果您关心性能,则应该对数据进行去规范化。

PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"question": ["answer", "comment"], ①
"answer": "vote" ②
}
}
}
}
}
}

question 是 answer 和comment 的父级

answer 是 vote 的父级

实现如下图的祖孙三代关联关系的定义。

question
/ \
/ \
comment answer
|
|
vote

文档必须位于与其父父级和父级相同的分片上:

PUT my_index/_doc/3?routing=1&refresh  ①
{
"text": "This is a vote",
"my_join_field": {
"name": "vote", ②
"parent": "2"
}
}

此子文档必须位于与其父父级和父级相同的分片上

此文档的父ID(必须指向answer文档)

elasticsearch 基础 —— Jion父子关系的更多相关文章

  1. elasticsearch 父子关系

    ElasticSearch 中的Parent-Child关系和nested模型是相似的, 两个都可以用于复杂的数据结构中,区别是 nested 类型的文档是把所有的实体聚合到一个文档中而Parent- ...

  2. 读《深入理解Elasticsearch》点滴-对象类型、嵌套文档、父子关系

    一.对象类型 1.mapping定义文件 "title":{ "type":"text" }, "edition":{ ...

  3. Logstash 父子关系 配置

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

  4. QObject提供了QMetaObject元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化

    元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化其中元类又提供了:classInfo,className,构造函数, ...

  5. margin collapse 之父子关系的DIV

    打算花点时间将知识整理一下,虽然平时现用现查都能完成工作,可是当遇到面试这种事情的时候,临时查就来不及了... 关于margin,整理若干知识点如下: 一:父子关系的DIV标签以及未加margin时的 ...

  6. iOS 父子关系

    1.面向对象特征,类的继承 成员变量(实例变量) 子类继承父类所有功能,只能直接(访问)调用父类中的.h中的protect和public成员变量(实例变量)及方法, .h中的私有的成员变量,子类不能直 ...

  7. [转]NHibernate之旅(9):探索父子关系(一对多关系)

    本节内容 引入 NHibernate中的集合类型 建立父子关系 父子关联映射 结语 引入 通过前几篇文章的介绍,基本上了解了NHibernate,但是在NHibernate中映射关系是NHiberna ...

  8. Qt 对象间的父子关系

    C++中只要有一个new就必须要有一个delete与之对应 但是Qt中的对象之间有特殊的关系 Qt 对象间的父子关系 每一个对象都保存有它所有子对象的指针 每一个对象都有一个指向其父对象的指针 par ...

  9. MFC窗口的父子关系和层级关系

    一直对窗口之间的关系有些混乱,遇到需要指定父窗口的函数时常常要考虑很久,究竟父窗口是哪个窗口,遂上网查资料,略有所悟,简记如下: 对话框中的所有控件(比如Button等)都是其子窗口.        ...

随机推荐

  1. Nginx+lua_Nginx+GraphicsMagick来实现实时缩略图

    1.安装GraphicsMagick cd /usr/local/src wget http://sourceforge.net/projects/graphicsmagick/files/graph ...

  2. 什么是Js原型?(1)(包括作用:继承)

    学习目标:    认识什么js是原型,原型.构成函数.实例对象关系:原型应用范围. 什么是原型    函数有原型,函数有一个属性叫prototype,函数的这个原型指向一个对象,这个对象叫原型对象.这 ...

  3. Python---基础---dict和set

    2019-05-20 ------------------------------ 写一个程序来管理用于登陆系统的用户信息:登录名字和密码,登录用户账号建立后,已存在用户可以用登陆名字和密码重返系统, ...

  4. 【leetcode】1091. Shortest Path in Binary Matrix

    题目如下: In an N by N square grid, each cell is either empty (0) or blocked (1). A clear path from top- ...

  5. 日志管理工具logrotate

    工作所需,需要管理脚本的打印日志,百度一圈,发现了logrotate这款工具,经测试确实挺好的! 话不多说,直接上重点,以便于以后需要时查看 命令: whereis logrotate 可以看到log ...

  6. Nginx实现反向代理与负载均衡

    1.什么是反向代理 使用nginx实现反向代理,Nginx只做请求的转发,后台有多个http服务器提供服务,nginx的功能就是把请求转发给后面的服务器,决定把请求转发给谁. 2.在一个虚拟机上创建两 ...

  7. centos6.5安装nginx1.16.0

    参考:   centos7 编译安装nginx1.16.0( 完整版 ) https://blog.csdn.net/weixin_37773766/article/details/80290939  ...

  8. php中换行怎么写

    PHP中可以用PHP_EOL来替代,以提高代码的源代码级可移植性 unix系列用(推荐学习:PHP编程从入门到精通) 1 windows系列用 1 \r\n mac用 1 如: 1 2 3 4 5 6 ...

  9. git config使用

    我们知道config是配置的意思,那么git config命令就是对git进行一些配置.而配置一般都是写在配置文件里面,那么git的配置文件在哪里呢?互动一下,先问下大家. 你们所知的git配置文件是 ...

  10. [CSP-S模拟测试]:Park(树上DP)

    题目描述 公园里有$n$个雕像,有$n-1$条道路分别连接其中两个雕像,任意两个雕像可以直接或间接相连.现在每个景点$i$聚集着$P_i$只鸽子,旅行家手里有$v$数量的面包屑. 一旦旅行家在雕像$i ...