ES入门十:关系模型的实现:嵌套类型和父子文档

现实中,关系模型是到处存在的,例如书本与作者的关系。但是在ES中想要处理这个事情并不简单

在ES中保存关系型模型数据的方式主要有以下几种:

  • nested:在这种方式中,会通过一对多的放系保存在同一个文档中
  • join(parent/child):通过维护文档的父子节点,将两个对象分离

上面这2种方式都可以描述一对多的关系,今天我们就来了解一下

nested(嵌套类型)

nested类型是一种特别的object类型,其允许数组中的对象可以被单独索引,使他们可以被独立地索引。下面的示例是使用普通的object数组来保存书本与作者的一对多关系,我们看看会产生什么问题

# 创建 Mapping
PUT books_index
{"mappings": {"properties": { "book_id": { "type": "keyword" },"author": { "properties": {"first_name": { "type": "keyword" },"last_name": { "type": "keyword" }}}}}
}# 写入书本数据
PUT books_index/_doc/1
{"book_id": "1234","author": [{ "first_name": "zhang", "last_name": "san" },{ "first_name": "wang", "last_name": "wu" }]
}

如上面的示例,我们创建了books_index索引,其中author字段是一个对象,包括了first_name与last_name两个属性,并且在我们写入数据的时候,书本的作者有两个(描述了一对多的关系):zhangsan和wangwu。

我们对上面的数据进行一个查询:
image.png
image.png
按道理来说我们的数据中是没有zhangwu这个作者的,但是在实际查询中能命中文档1,为什么那?
因为object被扁平化指挥,其丢失了first_name和last_name之间的关系,变成了下面这样的关系
image.png
对于这个扁平化的数组,原先first_name和last_name见的关系当然以及不复存在了。所以我们的查询语句在author.first_name中匹配了“zhang”,在author.last_name匹配了“wu”,自然就命中了文档1,那么有什么办法解决这个问题吗?
那就是使用nested数据类型,他可以是对象数组的对象被独立索引,这样fist_name和last_name之间的关系就不会丢失了。下面我们修改一下mapping,把author的类型定义为nested:
image.png
如上所示,使用nested关键字指定一个nested对象的查询,使用path指定nested对象的名字。

从上面的示例来看,nested通过冗余的方式将对象和文档存储在一起,所以查询时的性能是很高的,但是需要更新对象的时候,需要更新所有包含此对象的文档,例如某个作者的信息更改了,那么所有这个作者的书本文档都需要更新。所以nested适合查询频繁但更新频率低的场景

parent/child(父子类型)

join数据类型允许在一个索引中的文档创建父子关系,通过维护父子文档的关系独立出来两个对象。父文档和自文档是相互独立的,通过类似引用的关系进行绑定,所以当父文档更新时,不需要更新自文档,而自文档可以被任意的添加、修改、删除而不会影响到父文档和其他自文档

需要注意的是,为了维护父子文档的关系需要占用额外的内存资源,并且读取性能相对较差。但是由于父子文档是互相独立的,所以适合自文档更新频率高的场景

在Mapping中定义join数据类型
PUT join_books_index
{"mappings": {"properties": { "book_id": { "type": "keyword" },"name": { "type": "text" },"book_comments_relation": { # 定义字段名字"type": "join", # 此字段为 join 类型"relations": { # 声明 Parent / Child 的关系"book": "comment" # book 是 Parent 的名称,comment 是 Child 的名称}}}},"settings": {"number_of_shards": 3, # 定义 3 个主分片"number_of_replicas": 1}
}

如上示例,book_comments_relation是字段的名字,使用join关键字定义此字段的类型为join类型,relations处声明了Parent/Child的关系,其中book是Parent的名称, comment是Child的名称

索引父文档(创建)

在定义了Mapping之后,我们写入父文档的数据

image.png

索引子文档(创建)

image.png
如上所示,book_comments_relation中声明了文档的类型为comment(即mapping中的自文档),并且使用parent字段指向父文档的id

为了确保查询时候的性能,父文档和子文档必须在同一个分片,所以需要强制使用routing参数,并且其值为父文档的Id(如果写入父文档的时候也用routing参数,那么需要保证他们的值是一样的)

数据检索

image.png
返回结果:
image.png

如图所示,我们在获取父文档的数据时候是不返回子文档的信息的,因为父子文档是相互独立的

获取子文档:
image.png
如上图所示,在获取子文档时,如果不加routing参数时,是无法找到对应的子文档的。routing参数的值为父文档的Id

parent id查询

image.png
如上所示,parent_id字段里面,我们查询了父文档Id为11并且comment类型的文档

返回结果:
image.png

has child查询

如果我们想查询用户“fork”评论了那些书本,可以使用 Has Child 查询。Has Child 查询将在子文档中进行条件匹配,然后返回匹配文档对应的父文档的信息
image.png
返回结果:
image.png

has parent查询

那如果我们想查询java相关书籍的评论时,可以使用Has Parent 查询。 Has Parent 查询会在父文档中进行匹配,然后返回匹配文档对应的子文档的信息。
image.png
返回结果:
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/513468.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android开发者必看,我的移动开发春季历程

热修复介绍 1.开发流程 当项目出现紧急bug时,传统的开发流程是发布新版本,引导用户覆盖安装。抛开平台审核上线的时间不说,一天重复下载安装至少两次的用户体验是很差的。而热修复的出现完美解决了这个问题,用户在收到服务器推送…

【原理图PCB专题】Allegro模块化移动器件报...has the LOCKED property怎么解锁?

在模块化原理图时,PCB也需要做一个模块.mdd文件。这时需要先画好图纸然后再制作模块化文件。 修改文件时会发现模块化器件报错,无法编辑模块内部器件和走线,器件和走线都被LOCKED,如下所示报错内容: Symbol "U1" Selected Cannot edit Symbol "U1". M…

【pyinstaller打包记录】Windows系统打包exe后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件(可执行程序)的工具。它能够将 Python 代码和其相关的依赖项(包括 Python 解释器、依赖的模块、库文件等)打包成一个独立的可执行文件,方便在不同环境中运行…

2024高频前端面试题 Vue2 和 Vue3 篇

* Vue2 和 Vue3的区别: 1)双向数据绑定原理的区别 2)根节点的不同 Vue2只能一个根节点 Vue3在组件中可以放置多个根节点 3)Vue3中采用composition API vue2:采用的选项型API(opsition API) vue3:采用的组合型API(composition A…

05_Mongooes

Mongooes Mongoose是通过Node来操作MongoDB的一个模块。是基于Node.js的第三方模块。 一、Node.js安装 1.解压 2.创建文件夹 解压路径下,创建两个文件夹 node_global:全局安装位置 node_cache:缓存 3.配置 配置环境变量 在path路径…

找不到msvcr100.dll怎么办,多种解决方法快速修复msvcr100.dll问题

当计算机系统中关键文件msvcr100.dll丢失时,可能会引发一系列运行问题和故障现象。msvcr100.dll是Microsoft Visual C Redistributable Package的一部分,对于许多基于Windows的应用程序正常运行至关重要。由于msvcr100.dll是许多应用程序运行所必需的动态…

Linux 防火墙 操作命令【实用】

防火墙操作: 描述命令查看防火墙状态systemctl status firewalld、firewall-cmd --state暂时关闭防火墙systemctl stop firewalld永久关闭防火墙systemctl disable firewalld开启防火墙systemctl start firewalld开放指定端口firewall-cmd --zonepublic --add-port…

ES入门六:Suggesters Api实践

都是负担在很多app上,当我们输入某些内容时候,它会立即做一些补全操作,如果我想实现上述的需求,我们就可以使用ES提供的Suggesters Api。那Suggesters是如何做到的那?简单来说,Suggesters会将输入的文本拆分…

Python 实现冒泡排序算法

Python 实现冒泡排序算法 下面是用 Python 实现的冒泡排序算法示例代码: def bubble_sort(arr):n len(arr)# 遍历数组元素for i in range(n):# 每次遍历都将最大的元素移动到最后for j in range(0, n-i-1):# 如果相邻的元素逆序,则交换它们if arr[j] …

Vue.js 深度解析:模板编译原理与过程

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

ES入门七:索引管理Api的使用

索引设置 在传家索引的时候,可以在“settings”字段中指定索引的位置。numbers_of_shards和nubmer_of_replicas 是索引非常重要的两个配置,设置它们值的示例如下: 我们还可以动态修改索引的位置,其示例如下:如上示例…

力扣404 左叶子之和 Java版本

文章目录 题目描述解题思路代码 题目描述 给定二叉树的根节点 root ,返回所有左叶子之和。 示例 1: 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 2…