首页 > 其他分享 >ES中如何实现类似having的先聚合再过滤查询

ES中如何实现类似having的先聚合再过滤查询

时间:2022-12-07 20:08:01浏览次数:30  
标签:name amount 过滤 avgAmount sql 100 having ES


一、问题描述:

在mysql数据库中,我们可以很方面的通过having关键字实现对聚合结果的过滤查询。那么,在ES中该如何实现类似having的先聚合再过滤查询呢?


二、业务场景:

需要找出下单次数大于等于2单,并且平均下单金额大于等于100的客户

在关系型数据库中对应的SQL语句:

SELECT 
userId,
AVG(amount) avgAmount,
count(*) orderCount
FROM order
GROUP by userId
HAVING avgAmount >= 100 and orderCount >=2

三、数据准备

创建订单索引order_index,并添加测试数据。

## 删除索引
## DELETE order_index
## 新建索引
PUT order_index
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"amount": {
"type": "integer"
}
}
}
}
## 添加数据
POST order_index/_bulk?refresh
{ "create": { } }
{ "name": "老万", "amount": 100}
{ "create": { } }
{ "name": "老万", "amount": 80}
{ "create": { } }
{ "name": "老万", "amount": 300}
{ "create": { } }
{ "name": "老王", "amount": 45}
{ "create": { } }
{ "name": "小明", "amount": 15}
{ "create": { } }
{ "name": "小明", "amount": 50}
{ "create": { } }
{ "name": "小红", "amount": 300}

四、具体实现

1、SQL实现方式

说明:由于ES6.3以后已经支持sql查询,所有首先尝试大家最熟悉的sql查询方案能否实现。

POST /_sql?format=txt
{
"query": "SELECT name,AVG(amount) avgAmount,count(*) orderCount FROM order_index group by name having avgAmount >= 100 and orderCount >=2 "
}

查询结果:

用户名为老万,满足平均订单金额大于100,且下单数大于2。

查询结果正确。

ES中如何实现类似having的先聚合再过滤查询_having

2、DSL实现方式

GET order_index/_search
{
"size": 0,
"aggs": {
"groupName": {
"terms": {
"field": "name"
},
"aggs": {
"avgAmount": {
"avg": {
"field": "amount"
}
},
"having": {
"bucket_selector": {
"buckets_path": {
"orderCount": "_count",
"avgAmount": "avgAmount"
},
"script": {
"source": "params.avgAmount >= 100 && params.orderCount >=2 "
}
}
}
}
}
}
}

查询结果:

{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 7,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"groupUserId" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "老万",
"doc_count" : 3,
"avgAmount" : {
"value" : 160.0
}
}
]
}
}
}

sql语句底层实现分析:

POST /_sql/translate
{
"query": "SELECT name,AVG(amount) avgAmount,count(*) orderCount FROM order_index group by name having avgAmount >= 100 and orderCount >=2 "
}

执行结果:
分析sql转化的DSL语句,和上面DSL语句的实现,说明两者底层实现原理一致。
mysql中通过having实现根据聚合结果进行过滤,ES中使用 bucket_selector 来实现此功能。

{
"size" : 0,
"_source" : false,
"stored_fields" : "_none_",
"aggregations" : {
"groupby" : {
"composite" : {
"size" : 1000,
"sources" : [
{
"7e80e5b2" : {
"terms" : {
"field" : "name",
"missing_bucket" : true,
"order" : "asc"
}
}
}
]
},
"aggregations" : {
"d8415567" : {
"avg" : {
"field" : "amount"
}
},
"having.having.d8415567_&_having.b26c7698" : {
"bucket_selector" : {
"buckets_path" : {
"a0" : "d8415567",
"a1" : "_count"
},
"script" : {
"source" : "InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.and(InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gte(params.a0,params.v0)),InternalQlScriptUtils.nullSafeFilter(InternalQlScriptUtils.gte(params.a1,params.v1))))",
"lang" : "painless",
"params" : {
"v0" : 100,
"v1" : 2
}
},
"gap_policy" : "skip"
}
}
}
}
}
}

具体实现

本文主要介绍了ES中如何实现类似having的先聚合再过滤查询。
1、介绍了基于sql和dsl的两种实现方式,但是二者的底层原理其实都是一样的。
2、实际项目中,更推荐直接采用sql来实现,代码简单,sql语句相比dsl上手更容易,也更容易理解。
3、mysql中通过having实现根据聚合结果进行过滤,ES中使用 bucket_selector 来实现此功能。


标签:name,amount,过滤,avgAmount,sql,100,having,ES
From: https://blog.51cto.com/u_15905482/5919983

相关文章

  • ES中如何实现like模糊查询
    问题描述:我们都知道ES针对复杂的多添加组合查询非常强大,也知道通过match可以实现全文检索查询(分词查询),但是如果现在我只需要实现类似mysql中的like全匹配模糊查询,该怎么实现......
  • SpringBoot整合elasticsearch-rest-client实战
    前言很多人在Springboot项目中都已经习惯采用Spring家族封装的spring-data-elasticsearch来操作elasticsearch,而官方更推荐采用rest-client。今天给大家介绍下在springbo......
  • 你的ES还在裸奔吗?还不赶紧开启X-Pack权限认证
    前言在es的早期版本中,没有免费提供安全认证的相关功能。为了防止数据安全问题,一般的措施都是采用IP黑白名单,网络防火墙,Nginx代理权限控制。而从es6.8和7.1版本开始,es给我......
  • 还不会ES?Elasticsearch快速入门实操指南送上
    前言本文主要介绍ES的常用请求,让大家能快速上手ES的使用主要参考官网的​​Quickstart​​指引。一、请求方式向Elasticsearch发送请求主要有2种方式:1、使用restapi发送h......
  • python-requests接入API
    API接入1APIApplicationProgrammingInterface,应用程序编程接口,是软件之间信息交互的桥梁。  2聚合数据(数据获取网站)网址:https://www.juhe.cn/docs/index/o......
  • CT data processing (2) data annotation and verification
    InCTimageprocessing,thesegmentationmodelusuallyservesasthefoundationpartforawiderangeofapplications.Totrainasegmentationmodel,anessent......
  • CodeStar2022年春第十一周周赛普及奠基组
    T1:牛奶供应本题难度简单,主要考察贪心算法。第\(i\)天的牛奶成本价为\(\min(c_i,minp+s)\),其中\(minp\)为前\(i-1\)天中牛奶的最低成本价代码实现#include<bit......
  • Response_验证码_分析以及代码实现
    Response_验证码_分析以及代码实现本质:图片目的:防止恶意表单注册步骤:1.创建对象,在内存中图片(验证码图片对象)2.美化图片3.将图片输出到页面展示package......
  • resnet详细解读
    原文链接:https://arxiv.org/abs/1512.03385摘要作者提出了一个残差学习结构用来解决非常深网络的退化问题和训练问题。原来的网络是为了拟合一个分布函数,我们重构了网络......
  • session,cookie,token详解
    session,cookie,token详解1.session1.1session的作用是什么session的作用是用于保存每个用户的专用信息;当用户访问时,服务器都会为每个用户分配唯一的SessionID,而且当......