ElasticSearch一对多关系方案

一、前言

使用MySQL做为存储,表与表之间有很多是一对多关系,比如订单和订单商品明细,客户和客户地址等等,但是因为ES本身是扁平化文档结构,一般不同索引之间是没有关系的,ES在处理这种关系时相比MySQL并不擅长,不过也提供了几种方式来支持这种关系,下面就以客户和客户地址(一个客户有多个地址)为例来讲述一下各种类型存储的优缺点,正好我们本周一个迭代要把客户数据迁移到ES中。


客户基本信息:first、last、code、email
客户地址信息:city、address

二、数组

ES中其实不存在专用的数组类型,默认情况任何字段都可以包含0个或多个值,不过数组中所有值都必须具有相同的数据类型。

1、基本类型数组

注:addr准备存入多个地址,这里定义为text即可,定义时并没有关键字来设置为数组类型。

注:可以放0或多个值,只要类型一致或可以强制转换就可以存入。

注:可以通过模糊查询查找到该DOC文档。

2、对象数组

注:这个其实就是ES中基本的Object类型

注:addr可以放内嵌对象。

注:对象数组查询结果存在边界问题,查city="Brisbane"并且

address="Ngungug"会把记录给查出来,像地址这里要求不严格的场景是没有什么问题,但是如果是订单内嵌产品列表,我要查出产品编码和价格是指定值的时候,其实是需要严格匹配数组中一个对象,而不是在整个数组中匹配。这个主要是因为ES对JSON对象数据是压扁了存储。

上面的数据实际内部的存储如下,这样存储是丢失了city与address之间映射关系。

三、嵌套

nested(嵌套)类型是object数据类型特殊版本,可以在对象中嵌套对象或者在字段中存储键值对。

1、定义嵌套结构

注:嵌套结构使用nested类型定义。

2、插入文档数据

注:嵌套结构中可以放多个地址信息,另外ES中的put和post指令区别,put需要指定文档ID作用在指定文档上,POST不需要指定文档ID,它是作用在集合上,这个概念源自HTTP协议,HTTP协议定义put操作是幂等的,而POST操作是非幂等的。

3、根据嵌套中内容去查询文档

如果查询换成如下,就不会查出数据,这个就是嵌套结构和对象数组的区别。

对象数据和嵌套存储的区别,使用命令

get _cat/indices?v 查看ES内部真实的文档数量。

可以看出使用nested结构 nested子文档在ES内部其实也是独立的子文档,只是在我们做查询时,ES内部帮我们做了Join处理,所以相对来讲nested在做查询时性能是不如普通内部对象。

四、父子文档

1、定义父子结构

注:使用join表示父子关联结构,relations里的custmoer是父文档,customerAddr是子文档。

2、插入父文档数据

注:这里join_field.name指定了该文档是父文档

3、插入子文档数据

注:这里join_field.name指定了该文档是子文档,parent指定了其父文档类型。请求中设置了routing确保了父子文档在相同的分片上。

4、查询

get customer_parent/_search{}

注:返回父子两个文档

get customer_parent/_doc/customer1

注:只返回父文档的数据

使用has_child查询 :根据子文档条件查询父文档内容

注:只返回父文档内容

使用has_parent查询:根据父文档条件查询子文档内容。

注:只返回子文档内容

五、ES一对多关系几种类型对比

注:我们的客户数据更新很少,大多数情况下是查询,所以最终采用的是nested结构。

猜你喜欢

转载自blog.csdn.net/2301_76787421/article/details/133427789
今日推荐