《ElasticSearch6.x实战教程》之父-子关系文档
第七章-父-子关系文档
关注公众号:CoderBuff,回复“es”获取《ElasticSearch6.x实战教程》完整版PDF。
打虎亲兄弟,上阵父子兵。
本章作为复杂搜索的铺垫,介绍父子文档是为了更好的介绍复杂场景下的ES操作。
在非关系型数据库数据库中,我们常常会有表与表的关联查询。例如学生表和成绩表的关联查询就能查出学会的信息和成绩信息。在ES中,父子关系文档就类似于表的关联查询。
背景
ES5.x开始借助父子关系文档实现多表关联查询,核心是一个索引Index下可以创建多个类型Type。但ES6.x开始只允许一个索引Index下创建一个类型Type,甚至在未来的版本中将会移除创建类型Type。为了继续支持多表关联查询,ES6.x推出了join新类型来支持父子关系文档的创建。
问题
假设现在有这样的需求场景:一个博客有多篇文章,文章有标题、内容、作者、日期等信息,同时一篇文章中会有评论,评论有评论的内容、作者、日期等信息,通过ES来存储博客的文章及评论信息。
此时文章本身就是"父",而评论就是"子",这类问题也可以通过nested嵌套对象实现,大部分情况下netsted嵌套对象和parent-child父子对象能够互相替代,但他们仍然不同的优缺点。下面将介绍这两种数据结构。
nested嵌套对象
一篇文章的数据结构如下图所示:
{
"title":"ElasticSearch6.x实战教程",
"author":"OKevin",
"content":"这是一篇水文",
"created":1562141626000,
"comments":[{
"name":"张三",
"content":"写的真菜",
"created":1562141689000
},{
"name":"李四",
"content":"辣鸡",
"created":1562141745000
}]
}
通过RESTful API创建索引及定义映射结构:
PUT http://localhost:9200/blog
{
"mappings":{
"article":{
"properties":{
"title":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"author":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"content":{
"type":"text",
"analyzer":"ik_smart"
},
"created":{
"type":"date"
},
"comments":{
"type":"nested",
"properties":{
"name":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"content":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"created":{
"type":"date"
}
}
}
}
}
}
}
插入数据:
POST http://localhost:9200/blog/article
{
"title":"ElasticSearch6.x实战教程",
"author":"OKevin",
"content":"这是一篇水文",
"created":1562141626000,
"comments":[{
"name":"张三",
"content":"写的真菜",
"created":1562141689000
},{
"name":"李四",
"content":"辣鸡",
"created":1562141745000
}]
}
POST http://localhost:9200/blog/article
{
"title":"ElasticSearch6.x从入门到放弃",
"author":"OKevin",
"content":"这是一篇ES从入门到放弃文章",
"created":1562144089000,
"comments":[{
"name":"张三",
"content":"我已入门",
"created":1562144089000
},{
"name":"李四",
"content":"我已放弃",
"created":1562144089000
}]
}
POST http://localhost:9200/blog/article
{
"title":"ElasticSearch6.x原理解析",
"author":"专家",
"content":"这是一篇ES原理解析的文章",
"created":1562144089000,
"comments":[{
"name":"张三",
"content":"牛逼,专家就是不一样",
"created":1562144089000
},{
"name":"李四",
"content":"大牛",
"created":1562144089000
}]
}
- 查询作者为“OKevin”文章的所有评论(父查子)
GET http://localhost:9200/blog/article/_search
{
"query":{
"bool":{
"must":[{
"match":{
"author.keyword":"OKevin"
}
}]
}
}
}
ES结果返回2条作者为"OKevin"的全部数据。
- 查询评论中含有“辣鸡”的文章(子查父)
GET http://localhost:9200/blog/article/_search
{
"query":{
"bool":{
"must":[{
"match":{
"author.keyword":"OKevin"
}
},{
"nested":{
"path":"comments",
"query":{
"bool":{
"must":[{
"match":{
"comments.content":"辣鸡"
}
}]
}
}
}
}]
}
}
}
ES确实只返回了包含"辣鸡"的数据。
两次查询都直接返回了整个文档数据。
parent-child父子文档
既然父子文档能实现表的关联查询,那它的数据结构就应该是这样:
文章数据结构
{
"title":"ElasticSearch6.x实战教程",
"author":"OKevin",
"content":"这是一篇实战教程",
"created":1562141626000,
"comments":[]
}
评论数据结构
{
"name":"张三",
"content":"写的真菜",
"created":1562141689000
}
ES6.x以前是将这两个结构分别存储在两个类型Type中关联(这看起来更接近关系型数据库表与表的关联查询),但在ES6.x开始一个索引Index只能创建一个类型Type,要再想实现表关联查询,就意味着需要把上述两张表揉在一起,ES6.x由此定义了一个新的数据类型——join。
通过RESTful API创建索引及定义映射结构:
{
"mappings":{
"article":{
"properties":{
"title":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"author":{
"type":"text",
"analyzer":"ik_smart",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"content":{
"type":"text",
"analyzer":"ik_smart"
},
"created":{
"type":"date"
},
"comments":{
"type":"join",
"relations":{
"article":"comment"
}
}
}
}
}
}
重点关注其中的"comments"字段,可以看到类型定义为join,relations定义了谁是父谁是子,"article":"comment"表示article是父comment是子。
父子文档的插入是父与子分别插入(因为可以理解为把多个表塞到了一张表里)。
插入父文档:
POST http://localhost:9200/blog/article/1
{
"title":"ElasticSearch6.x实战教程",
"author":"OKevin",
"content":"这是一篇水文",
"created":1562141626000,
"comments":"article"
}
POST http://localhost:9200/blog/article/2
{
"title":"ElasticSearch6.x从入门到放弃",
"author":"OKevin",
"content":"这是一篇ES从入门到放弃文章",
"created":1562144089000,
"comments":"article"
}
POST http://localhost:9200/blog/article/3
{
"title":"ElasticSearch6.x原理解析",
"author":"专家",
"content":"这是一篇ES原理解析的文章",
"created":1562144089000,
"comments":"article"
}
插入子文档:
POST http://localhost:9200/blog/article/4?routing=1
{
"name":"张三",
"content":"写的真菜",
"created":1562141689000,
"comments":{
"name":"comment",
"parent":1
}
}
POST http://localhost:9200/blog/article/5?routing=1
{
"name":"李四",
"content":"辣鸡",
"created":1562141745000,
"comments":{
"name":"comment",
"parent":1
}
}
POST http://localhost:9200/blog/article/6?routing=2
{
"name":"张三",
"content":"我已入门",
"created":1562144089000,
"comments":{
"name":"comment",
"parent":2
}
}
POST http://localhost:9200/blog/article/7?routing=2
{
"name":"李四",
"content":"我已放弃",
"created":1562144089000,
"comments":{
"name":"comment",
"parent":2
}
}
POST http://localhost:9200/blog/article/8?routing=3
{
"name":"张三",
"content":"牛逼,专家就是不一样",
"created":1562144089000,
"comments":{
"name":"comment",
"parent":3
}
}
POST http://localhost:9200/blog/article/9?routing=3
{
"name":"李四",
"content":"大牛",
"created":1562144089000,
"comments":{
"name":"comment",
"parent":3
}
}
如果查询索引数据会发现一共有9条数据,并不是nested那样将"评论"嵌套"文章"中的。
- 查询作者为“OKevin”文章的所有评论(父查子)
GET http://localhost:9200/blog/article/_search
{
"query":{
"has_parent":{
"parent_type":"article",
"query":{
"match":{
"author.keyword":"OKevin"
}
}
}
}
}
ES只返回了comment评论结构中的数据,而不是全部包括文章数据也返回。这是嵌套对象查询与父子文档查询的区别之一——子文档可以单独返回。
- 查询评论中含有“辣鸡”的文章(子查父)
GET http://localhost:9200/blog/artice/_search
{
"query":{
"has_child":{
"type":"comment",
"query":{
"match":{
"content":"辣鸡"
}
}
}
}
}
ES同样也只返回了父文档的数据,而没有子文档(评论)的数据。
nested嵌套对象和parent-child父子文档之间最大的区别,嵌套对象中的"父子"是一个文档数据,而父子文档的中的"父子"是两个文档数据。这意味着嵌套对象中如果涉及对嵌套文档的操作会对整个文档造成影响(重新索引,但查询快),包括修改、删除、查询。而父子文档子文档或者父文档本身就是独立的文档,对子文档或者父文档的操作并不会相互影响(不会重新索引,查询相对慢)。
关注公众号:CoderBuff,回复“es”获取《ElasticSearch6.x实战教程》完整版PDF。

《ElasticSearch6.x实战教程》之父-子关系文档的更多相关文章
- 《ElasticSearch6.x实战教程》正式推出(附图书抽奖)
经过接近1个月的时间,ElasticSearch6.x实战教程终于成册.这本实战教程小册有很多不足(甚至可能有错误),也是第一次完整推出一个系列的教程. 1年前,我开始真正接触ES,在此之前仅停留在知 ...
- 《ElasticSearch6.x实战教程》之准备工作、基本术语
第一章-准备工作 工欲善其事必先利其器 ElasticSearch安装 ElasticSearch6.3.2下载地址(Linux.mac OS.Windows通用,下载zip包即可):https:// ...
- 《ElasticSearch6.x实战教程》之简单的API
第三章-简单的API 万丈高楼平地起 ES提供了多种操作数据的方式,其中较为常见的方式就是RESTful风格的API. 简单的体验 利用Postman发起HTTP请求(当然也可以在命令行中使用curl ...
- 《ElasticSearch6.x实战教程》之简单搜索、Java客户端(上)
第五章-简单搜索 众里寻他千百度 搜索是ES的核心,本节讲解一些基本的简单的搜索. 掌握ES搜索查询的RESTful的API犹如掌握关系型数据库的SQL语句,尽管Java客户端API为我们不需要我们去 ...
- 《ElasticSearch6.x实战教程》之复杂搜索、Java客户端(下)
第八章-复杂搜索 黑夜给了我黑色的眼睛,我却用它寻找光明. 经过了解简单的API和简单搜索,已经基本上能应付大部分的使用场景.可是非关系型数据库数据的文档数据往往又多又杂,各种各样冗余的字段,组成了一 ...
- 《ElasticSearch6.x实战教程》之分词
第四章-分词 下雨天留客天留我不留 本打算先介绍"简单搜索",对ES的搜索有一个直观的感受.但在写的过程中发现分词无论如何都绕不过去.term查询,match查询都与分词息息相关, ...
- 《ElasticSearch6.x实战教程》之实战ELK日志分析系统、多数据源同步
第十章-实战:ELK日志分析系统 ElasticSearch.Logstash.Kibana简称ELK系统,主要用于日志的收集与分析. 一个完整的大型分布式系统,会有很多与业务不相关的系统,其中日志系 ...
- iOS Sprite Kit教程之使用帮助文档以及调试程序
iOS Sprite Kit教程之使用帮助文档以及调试程序 IOS中使用帮助文档 在编写代码的时候,可能会遇到很多的方法.如果开发者对这些方法的功能,以及参数不是很了解,就可以使用帮助文档.那么帮助文 ...
- HTML5实战与剖析之跨文档消息传递(iframe传递信息)
在来自不同域名的页面间传递消息一般统称为跨文档消息传送,简称XDM.如,www.leemagnum.com域中的页面与位于一个内嵌框架中的http://blog.csdn.net/lee_magnum ...
随机推荐
- 如何使用C#创建Windows Webcam应用
原文:如何使用C#创建Windows Webcam应用 最近想用C#写一个camera的应用.搜索了Google和StackOverflow,发现大部分的sample用了WIA或者DirectShow ...
- Delphi的对象注销方法Destroy和free
当您使用完对象后,您应该及时撤销它,以便把这个对象占用的内存释放出来.您可以通过调用一个注销方法来撤销您的对象,它会释放分配给这个对象的内存. Delphi的注销方法有两个:Destroy和Free. ...
- QT 那些事
一直做的是windows开发,有2个小项目想做到手机.看来看去,选择了QT.本文介绍自己的学习的一些心得,希望对你有帮助.1.选择QT2.安卓的一些事3.QML调用C++4.资源集成(比较有用,网上资 ...
- qtchooser - a wrapper used to select between Qt development binary(2种方法)
---------------------------------------------------------------------------------------------------- ...
- delphi7 xml通用解析转换为stringgrid
对于有n多记录的xml,可以填充到stringgrid中 其中 vkeynode 为 xml中 重复节点 function CommonAnalyzeXml(vxml,vkeynode: string ...
- 基于SAP HANA平台的多团队产品研发
工欲善其事必先利其器.要提高多团队的开发效率,而且还是在SAP HANA平台上,建议大家还是本着“慢就是快”的原则,不要急功近利,在没有准备好团队开发的架构时就匆忙开始功能的开发.匆忙功能开发就算了, ...
- 第二章 python如何运行程序
一.python解释器介绍 Python解释器是一种让程序运行起来的程序.实际上,解释器是代码与机器的计算机硬件之间的软件逻辑层.当Python包安装在机器上后,它包含了一些最小化的组件:一个解释器和 ...
- 【web自动化测试】requests-html 这个解析库,能让你更轻松的获取网页内容
1. 开始 Python 中可以进行网页解析的库有很多,常见的有 BeautifulSoup 和 lxml 等.在网上玩爬虫的文章通常都是介绍 BeautifulSoup 这个库,我平常也是常用这个库 ...
- 09 audio和vedio标签
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- c#基础三
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...