Elasticsearch 之 join 关联查询及使用场景

这篇具有很好参考价值的文章主要介绍了Elasticsearch 之 join 关联查询及使用场景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Elasticsearch这样的分布式系统中执行类似SQL的join连接是代价是比较大的,然而,Elasticsearch却给我们提供了基于水平扩展的两种连接形式 。这句话摘自Elasticsearch官网,从“然而”来看,说明某些场景某些情况下我们还是可以使用的

一、join总述

1、关系类比

在关系型数据库中,以MySQL为例,尤其B端类系统且数据量不是特别大的场景,我们经常用到join关键字对有关系的两张或者多张表进行关联查询。但是当数据量达到一定量级时,查询性能就是经常困扰的问题。由于es可以做到数亿量级的秒查(具体由分片数量决定),这时候把数据同步到es是我们可以使用解决方案之一。

那么不禁有疑问问了,由于业务场景的决定,之前必须关联查询的两张表还能做到进行关联吗?

答案是可以的,es也提供了类似于关系型数据库的关联查询,但是它又与关系型数据的关联查询有明显的区别与限制。

2、使用场景

如果把关系数据库原有关联的两张表,同步到es后,通常情况下,我们业务开发中会有两种查询诉求的场景

场景1

诉求:展示子表维度的明细数据(包含父表和子表中字段的条件)

方案:对于此种查询诉求,我们可以把原来关联的父子表打成父子表字段混合在一起的大宽表,既能满足查询条件,又有查询性能的保障,也是常用存储方案之一

场景2

诉求:展示父表维度的明细数据(包含父表和子表中字段的条件)

方案:然而,对于此种查询诉求,需要通过子表的条件来查询出父表的明细结果,场景1的宽表存储方案是子表明细数据,而最终我们要的是父表明细数据,显然对于场景1的存储方案是不能满足的。如果非要使用场景1的存储方案,我们还要对宽表结果进行一次groupby或者collapse操作来得到父表结果。

这个时候我们就可以使用es提供的join功能来完成场景2的诉求查询,同时它也满足场景1的诉求查询

3、使用限制

由于es属于分布式文档型数据库,数据自然是存在于多个分片之上的。Join字段自然不能像关系型数据库中的join使用。在es中为了保证良好的查询性能,最佳的实践是将数据模型设置为非规范化文档,通过字段冗余构造宽表,即存储在一个索引中。需要满足条件如下:

(1)父子文档(数据)必须存储在同一index中

(2)父子文档(数据)必须存储在同一个分片中,通过关联父文档ID关联

(3)一个index中只能包含一个join字段,但是可以有多个关系

(4)同一个index中,一个父关系可以对应多个子关系,一个子关系只对应一个父关系

4、性能问题

当然执行了join查询固然性能会受到一定程度的影响。对于带has_child/has_parent而言,其查询性能会随着指向唯一父文档的匹配子文档的数量增加而降低。本文开篇第一句摘自es官网描述,从ES官方的描述来看join关联查询对性能的损耗是比较大的。

不过,在笔者使用的过程中,在5个分片的前提下,且父表十万量级,子表数据量在千万量级的情况下,关联查询的耗时还是在100ms内完成的,对于B端许多场景还是可以接受的。

若有类似场景,建议我们在使用前,根据分片的多少和预估未来数据量的大小提前做好性能测试,防止以后数量达到一定程度时,性能有明显下降,那个时候再改存储方案得不偿失。

二、Mapping

1、举例说明

这里以优惠券活动与优惠券明细为例,在一个优惠券活动中可以发放几千万的优惠券,所以券活动与券明细是一对多的关系。

券活动表字段

字段 说明
activity_id 活动ID
activity_name 活动名称

券明细表字段

字段 说明
coupon_id 券ID
coupon_amount 券面额
activity_id 外键-活动ID

2、mapping释义

join类型的字段主要用来在同一个索引中构建父子关联关系。通过relations定义一组父子关系,每个关系都包含一个父级关系名称和一个或多个子级关系名称

activity_coupon_field是一个关联字段,内部定义了一组join关系,该字段为自命名

type指定关联关系是join,固定写法

relations定义父子关系,activity父类型名称,coupon子类型名称,名称均为自命名

{
	"mappings": {
		"properties": {
			"activity_coupon_field": {
				"type": "join",
				"relations": {
					"activity": "coupon"
				}
			},
			"activity_id": {
				"type": "keyword"
			},
			"activity_name": {
				"type": "keyword"
			},
			"coupon_id": {
				"type": "long"
			},
			"coupon_amount": {
				"type": "long"
			}
		}
	}
}

三、插入数据

1、插入父文档

在put父文档数据的时候,我们通常按照某种规则指定文档ID,方便子文档数据变更时易于得到父文档ID。比如这里我们用activity_id的值:activity_100来作为父id

PUT /coupon/_doc/activity_100
 
{
	"activity_id": 100,
	"activity_name": "年货节5元促销优惠券",
	"activity_coupon_field": {
		"name": "activity"
	}
}

2、插入子文档

上边已经指定了父文档ID,而子表中已经包含有activity_id,所以很容易得到父文档ID

put子文档数据时候,必须指定父文档ID,就是父文档中的_id,这样父子数据才建立了关联关系。与此同时还要指定routing字段为父文档ID,这样保证了父子数据在同一分片上。

PUT /coupon/_doc/coupon_12345678?routing=activity_id_100
 
{
	"coupon_id": 12345678,
	"coupon_amount": "5",
	"activity_id": 100,
	"activity_coupon_field": {
		"name": "coupon",
		"parent": "activity_id_100" //父ID
	}
}

四、关联查询

1、has_parent查询(父查子)

根据父文档条件字段查询符合条件的子文档数据

例如:查询包含“年货节”活动字样,且已经被领取过的券

{
	"query": {
		"bool": {
			"must": [{
				"parent_type": "activity",
				"has_parent": {
					"query": {
						"bool": {
							"must": [{
								"term": {
									"status": {
										"value": 1
									}
								}
							}, {
								"wildcard": {
									"activity_name": {
										"wildcard": "*年货节*"
									}
								}
							}]
						}
					}
				}
			}]
		}
	}
}

2、has_child查询(子查父)

根据子文档条件字段符合条件的父文档数据

例如:查询coupon_id=12345678在那个存在于哪个券活动中

{
	"query": {
		"bool": {
			"must": [{
				"has_child": {
					"type": "coupon",
					"query": {
						"bool": {
							"must": [{
								"term": {
									"coupon_id": {
										"value": 12345678
									}
								}
							}]
						}
					}
				}
			}]
		}
	}
}

参考:Joining queries | Elasticsearch Guide [7.9] | Elastic

以上文中如有不正之处欢迎留言指正

作者:京东零售 李振乾

内容来源:京东云开发者社区文章来源地址https://www.toymoban.com/news/detail-458792.html

到了这里,关于Elasticsearch 之 join 关联查询及使用场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • RestHighLevelClient实现ElasticSearch关联查询之父子文档

    RestHighLevelClient实现ElasticSearch关联查询之父子文档今天分享,承接上一篇内容: DSL操作关联查询 这篇我们通过javaAPI的方式实现: 一、springboot 配置 1、pom文件引用: 2、初始化配置es操作类 3、业务层引用 二、核心伪代码 1、创建父子索引 kibana查看 2、判断索引是否存在 3、删

    2024年02月10日
    浏览(42)
  • 如果elasticsearch要实现在大于两个索引之间关联查询怎么实现

    Elasticsearch可以通过多种方式在多个索引之间进行关联查询。 一种常用的方法是使用关联查询(join query), 这需要在索引和类型中使用 _join 字段来存储关联关系。 另一种方法是使用查询时连接(query time join),使用过滤器上下文来连接不同索引中的文档。 还可以使用 Elasticsearch 的聚

    2024年02月08日
    浏览(63)
  • mysql数据库递归查询树形结构(适用场景:菜单多级分类,多级关联评论查询),用strea流把list转成树的方法详解

    层次关系: 现在的需求是把这个层级关系,在前端显示出来,后端的处理方法有两种: 1.直接把全部的数据从数据库中拿到,然后在java代码里面使用树形结构来进行解析,但是这种做法只能在数据量比较小的时候使用,然后数据量一大会造成内存溢出 2.在mysql中创建一个函数

    2024年02月05日
    浏览(40)
  • HIVE 3 使用 MR 引擎多表关联 (JOIN) 导致丢数的问题复现、问题根源及解决方案 (附代码)

    本文意图解决 HIVE 3 版本中使用 MR 作为运算引擎进行 JOIN 操作时导致的丢数情况。 Apache Hive 在 2.3 版本后宣布放弃维护 MapReduce 作为底层执行引擎,并转而使用 Tez 作为默认的查询引擎。但是由于 Tez 在大作业量和高并发时的严重性能问题,导致许多任务不得不继续使用 MapRe

    2024年02月13日
    浏览(36)
  • MySQL多表查询内连接外连接详解,join、left join、right join、full join的使用

    目录 1、多表查询概览 1.1、分类 1.2、外连接的分类 1.3、常用的SQL语法标准 2、内外联接案例 2.1、初始化表 2.2、内连接 2.3、外连接案例 2.4、全连接案例 2.5、union和union all 2.6、实现MySQL全连接 2.7、内外连接面试基础 2.8、SQL99多表查询新特性 1.1、分类 可以根据3个角度进行分类

    2024年02月05日
    浏览(61)
  • 使用JOIN查询数据重复,怎么办?使用count统计怎么写SQL?

    比如现在有两个表tbl_a和tbl_b,如下: tbl_a id name 1 Bruce 2 Mike 3 Angela tbl_b id a_id :-: :-: 1 1 2 1 3 2 4 3 5 3 6 3 这时候我们如果联查的话,就会出现重复数据: 这样查出来的数据就会像下面这样: id name 1 Bruce 1 Bruce 2 Mike 3 Angela 3 Angela 3 Angela 去重的方法有三种: 一、distinct 二、group

    2024年02月16日
    浏览(51)
  • 你真的懂join吗?解决联表查询不使用索引问题

    小弟最近在开发一个项目时遇到了有点困扰我的问题,很有意思,而且也值得记录一下,希望对大家有用 场景: 我们有两个表,一个订单表表示t1,一个是订单的明细表t2,t2表中包含用户购买的各个产品,他们是根据订单编号关联的,当我用t1作为驱动表left join 连接t2表时没

    2024年01月17日
    浏览(37)
  • Flink多流处理之join(关联)

    Flink的 API 中只提供了 join 的算子,并没有 left join 或者 right join ,这里我们就介绍一下 join 算子的使用,其实 join 算子底层调用的就是 coGroup ,具体原理这里就不过多介绍了,如果感兴趣可以看我前面发布的文章Flink多流操作之coGroup. 数据源 代码 结果 这个 API 使用起来还是比较简单

    2024年02月13日
    浏览(35)
  • Mysql表关联简单介绍(inner join、left join、right join、full join不支持、笛卡尔积)

    A 是1、2、3 B是2、3、4 A、B的交集是A∩B = 2、3 A、B的并集是 AUB = 1、2、3、4 A、B的差集是 A-B = 1 B、A的差集是 B-A = 4 造数据 select A. ,B. from xin_stu_t_bak A inner join xin_teach_t_bak B on A.relation_id = B.id order by A.id; select distinct A. ,B. from xin_stu_t_bak A inner join xin_teach_t_bak B on A.relation_id = B.id

    2024年01月17日
    浏览(51)
  • hive表的全关联full join用法

    背景:实际开发中需要用到全关联的用法,之前没遇到过,现在记录一下。需求是找到两张表的并集。 全关联的解释如下; 下面建两张表进行测试 test_a表的数据如下 test_b表的数据如下; 写第一个full join 的SQL进行查询测试 查询结果显示如下; 把两个表的结果拼在一行了,

    2024年02月11日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包