ElasticSearch使用elasticsearchTemplate聚合查询

2023-05-16

这两天正好做个需求,需要用到聚合查询。前几篇文章只是简单的提到过,并没有真正的运用到实际产出中,本篇结合实际代码,专项学习ES的聚合查询。

1、业务背景

有一张地址索引表:
在这里插入图片描述
hisAddress与formatAddress是一对多的关系。
当一条地址进来查找hisAddress,然后对formatAddress做聚合,再根据count筛选聚合中的数据。
类似以下SQL:

select hisAddress,formatAddress,count(*) from addressIndex 
where hisAddress = "上海市静安区静安路100号静安寺" 
group by formatAddress having count(*) > 10

当然逻辑比这个稍稍复杂,需要使用嵌套聚合筛选数据。
流程如下:
在这里插入图片描述

2、elasticsearch的query

{
"size":0,
"query":{
	"bool":{
		"filter":{
			"term":{
				"hisAddress":"上海市上海市静安区静安路100号静安寺"
			}
		}
	}
},
"aggs":{
	"format_address":{		
			"terms":{
				"field":"formatAddress" 
			},
			
			"aggs":{
				"sign_org":{
					"terms":{
						"field":"signOrgCode"
					}
				},
				
				"having":{
					"bucket_selector":{
						"buckets_path":{
							"formatCount":"_count"		
						},
						"script":{						
		            		"inline": " formatCount>10"
						}							
					}
				},
			
				"stats_sign_bulk":{
					"stats_bucket":{
						"buckets_path":"sign_org > _count"
					}
				}
			}
	}
}
}

返回结果:

{
    "took": 19,
    "timed_out": false,
    "_shards": {
        "total": 6,
        "successful": 6,
        "failed": 0
    },
    "hits": {
        "total": 67,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "format_address": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "上海市上海市静安区静安寺",
                    "doc_count": 21,
                    "sign_org": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {
                                "key": "022795",
                                "doc_count": 21
                            }
                        ]
                    },
                    "stats_sign_bulk": {
                        "count": 1,
                        "min": 21,
                        "max": 21,
                        "avg": 21,
                        "sum": 21
                    }
                },
                {
                    "key": "上海市上海市静安区静安路100号",
                    "doc_count": 21,
                    "sign_org": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {
                                "key": "022795",
                                "doc_count": 21
                            }
                        ]
                    },
                    "stats_sign_bulk": {
                        "count": 1,
                        "min": 21,
                        "max": 21,
                        "avg": 21,
                        "sum": 21
                    }
                },
                {
                    "key": "上海市上海市静安区肯德基",
                    "doc_count": 16,
                    "sign_org": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {
                                "key": "01111",
                                "doc_count": 16
                            }
                        ]
                    },
                    "stats_sign_bulk": {
                        "count": 1,
                        "min": 16,
                        "max": 16,
                        "avg": 16,
                        "sum": 16
                    }
                }
            ]
        }
    }
}

3、elasticsearchTemplate的实现

String hisAddress = "上海市上海市静安区静安路100号静安寺";
List<HistoryIndexDocument> prepareList = new ArrayList<HistoryIndexDocument>();
Map<String,String> bucketMap = new HashMap<String, String>();
bucketMap.put("formatCount", "_count");

// 根据全量地址和寄派类型查询数据(此处使用filter过滤,它能缓存数据且不参与计算分值,比query速度快)
QueryBuilder queryBuilder = QueryBuilders
		.boolQuery()
		.filter(QueryBuilders.termQuery("hisAddress", entity.getHisAddress()))
		.filter(QueryBuilders.termQuery("rangeType", entity.getRangeType()));
	// 结构化地址聚合桶
TermsBuilder format_address_aggs = AggregationBuilders.terms("format_address_aggs").field("formatAddress");
	// 签收网点聚合桶
TermsBuilder sign_org_aggs = AggregationBuilders.terms("sign_org_aggs").field("signOrgCode");
// 管道聚合,类似having count(*) > 10
BucketSelectorBuilder bucketSelectorBuilder = PipelineAggregatorBuilders
 			.having("having")
 			.setBucketsPathsMap(bucketMap)
 			.script(new Script("formatCount>10"));

// 嵌套聚合,类似在group by formatAddress的基础上再group by signOrgCode
format_address_aggs.subAggregation(sign_org_aggs);
// 嵌套聚合,筛选数量大于10的结构化地址
format_address_aggs.subAggregation(bucketSelectorBuilder);
// 嵌套聚合,筛选数量大于10的签收网点
sign_org_aggs.subAggregation(bucketSelectorBuilder);

SearchQuery searchQuery = new NativeSearchQueryBuilder()
		.withIndices("my_index").withTypes("my_type")
		.withQuery(queryBuilder)
		.withPageable(new PageRequest(0, 1, null))
		.addAggregation(format_address_aggs)
		.build();

// 执行语句获取聚合结果
Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor<Aggregations>() {

	@Override
	public Aggregations extract(SearchResponse response) {
		return response.getAggregations();
	}
});

// 获取聚合结果
StringTerms teamAgg = (StringTerms) aggregations.asMap().get("format_address_aggs");
List<Bucket> bucketList = teamAgg.getBuckets();
for(Bucket bucket:bucketList) {
	// 结构化地址
	String formatAddress = bucket.getKeyAsString();
	System.out.println(formatAddress);
	
	Aggregations signAggs = bucket.getAggregations();
	StringTerms signTerms = (StringTerms) signAggs.asMap().get("sign_org_aggs");
	List<Bucket> signBucketList = signTerms.getBuckets();
	// 签收网点只能一个
	if(signBucketList==null || signBucketList.size() >1) {
		continue;
	}
	
	Bucket signBucket = signBucketList.get(0);
	// 签收频次需要5次以上
	if(signBucket.getDocCount() >= 5) {
		
		// 满足条件的网点放入prepareList
		HistoryIndexDocument entity = new HistoryIndexDocument();
		entity.setFormatAddress(formatAddress);
		entity.setSignOrgCode(signBucket.getKeyAsString());
		prepareList.add(entity);
	}
}

System.out.println(FastJsonUtil.toJsonString(prepareList));

4、更多java API聚合的用法

//(1)统计某个字段的数量
  ValueCountBuilder vcb=  AggregationBuilders.count("count_uid").field("uid");
//(2)去重统计某个字段的数量(有少量误差)
 CardinalityBuilder cb= AggregationBuilders.cardinality("distinct_count_uid").field("uid");
//(3)聚合过滤
FilterAggregationBuilder fab= AggregationBuilders.filter("uid_filter").filter(QueryBuilders.queryStringQuery("uid:001"));
//(4)按某个字段分组
TermsBuilder tb=  AggregationBuilders.terms("group_name").field("name");
//(5)求和
SumBuilder  sumBuilder=	AggregationBuilders.sum("sum_price").field("price");
//(6)求平均
AvgBuilder ab= AggregationBuilders.avg("avg_price").field("price");
//(7)求最大值
MaxBuilder mb= AggregationBuilders.max("max_price").field("price"); 
//(8)求最小值
MinBuilder min=	AggregationBuilders.min("min_price").field("price");
//(9)按日期间隔分组
DateHistogramBuilder dhb= AggregationBuilders.dateHistogram("dh").field("date");
//(10)获取聚合里面的结果
TopHitsBuilder thb=  AggregationBuilders.topHits("top_result");
//(11)嵌套的聚合
NestedBuilder nb= AggregationBuilders.nested("negsted_path").path("quests");
//(12)反转嵌套
AggregationBuilders.reverseNested("res_negsted").path("kps ");

了解更多详情,请参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/search-aggregations.html
本文参考:https://blog.csdn.net/u010454030/article/details/63266035

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ElasticSearch使用elasticsearchTemplate聚合查询 的相关文章

随机推荐

  • 任务栈简单入门

    最近又把两本进阶书看了一遍 xff0c 但总感觉好记性不如烂笔头 xff0c 所以还是决定通过博客记录一下 xff0c 我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容 android任务栈简单了解 1 android任
  • VS2010里函数枚举

    一 cout函数 说明 xff1a 调用该函数必须申明头文件 include lt iostream gt 同时声明后面必须使用 using namespace std 正确书写为 xff1a include lt iostream gt
  • I_O—标准 I_O 实验

    一 测试标准 I O 一次可以同时打开多少个文件 1 实验思路 xff1a 利用循环同时打开文件 xff0c 直到不能打开 2 代码如下 xff1a 二 fgetc 和 fputc 实现拷贝文件并输出文件行数 1 实验思路 xff1a 打开
  • Source Insight 配色方案

    Source Insight 对于程序员来说应该不陌生 xff0c 当然一个个性化的编程界面也会让自己赏析悦目 xff0c 下面就将个人的界面设置分享一下 xff1a 一 背景色设置 1 选择 Options Preferences 2 选
  • Linux 网络——交换机不能用两根网线相连

    同一个局域网所有的交换机之间可以用网线串联起来 xff0c 但绝对不能使任意 gt 61 2个交换机形成环路 xff0c 否则局域网内将形成广播风暴 xff0c 所用局域网内的用户都将不能上网 例如局域网内的交换机可以使用如下相连 xff1
  • GDB 知识点——基础操作

    Linux C 中的 GDB 调试使用 xff1a 1 GDB 的主要功能 xff1a 1 启动被调试程序 2 让被调试的程序在指定的位置停住 3 当程序被停住时 xff0c 可以检查程序状态 xff08 如变量的值 xff09 2 检查
  • 员工管理系统(C 语言)——项目说明

    项目名称 xff1a 员工管理系统 项目目的 xff1a 1 实现简单的公司对员工信息的管理 2 通过项目锻炼实现逻辑转换为代码的能力 3 利用函数封装实现项目过程中的逻辑过程以及需求功能的实现 4 学会数据库的操作以及网络通信 5 强化代
  • 员工管理系统(C 语言)——客户端解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 客户端功能 xff1a 1 运行时先测试是否能连通服务器 xff08 不畅通如下图所示 xff09 xff
  • 员工管理系统(C 语言)——服务器解析

    源码下载地址 xff1a https download csdn net download wenfei11471 10477504 服务器功能 xff1a 1 运行时主界面 xff08 服务器启动后 xff0c 只有管理员下线 xff0c
  • 排序——选择排序、冒泡排序和快速排序比较

    一 选择排序思路 xff1a 1 以 int 类型为例 2 拿第一个数与后面数相比较 xff0c 如果比后面的数大则交换 3 拿第二个数与后面的数比较 xff0c 如果比后面的数大则交换 4 直到比较到倒数第二个数 xff0c 最后一个数不
  • C 语言中 const 与指针的结合使用

    请区分一下几种指针的区别 1 const int p 2 int const p 3 int const p 4 const int const p 5 const int const p 解析 xff1a 1 const int p 中
  • Ubuntu16.04上安装百度网盘后打不开

    现在百度网盘推出了Linux版本 xff0c 也有Ubuntu下安装的deb文件 xff0c 但是我在Ubuntu上安装后却打不开 xff0c 报错 baidunetdisk crashed with SIGABRT in gnu cxx
  • C/C++的“文件包含”处理时头文件被重复包含的问题探究及解决方法(用最简单的例子进行说明)

    这篇博文是博文https blog csdn net wenhao ir article details 125668051的配套博文 头文件被重复包含是下面这样的现象 xff1a A文件里包含了C文件 xff0c B文件里也包含了C文件
  • BIN,BCD,ASCII码分别对应的Hex(16进制)数

    BIN BCD ASCII码分别对应的Hex xff08 16进制 xff09 数 以十进制的 56 为例 BIN 码 对应二进制数为 0011 1000对应Hex数据为 0x38BIN码就是二进制数 xff1b 压缩BCD 码 对应二进制
  • .LDS 文件详解

    最近在研究uboot xff0c 红色部分为我加上的注解 转载地址 xff1a http blog chinaunix net space php uid 61 23373524 amp do 61 blog amp cuid 61 232
  • 13 select的优化一

    1 上个例子中 xff0c select通过for循环轮询client套接字 xff0c 轮询的范围比较大 xff0c 有优化的地方 2 优化代码 xff1a 通过数组存储client的套接字 xff0c 达到少轮询的效果 xff0c 可以
  • 二.手写迷你版Tomcat-minicat2.0

    minicat 1 0我们实现了返回固定的字符串 34 Hello minicat 34 minicat 2 0需求 xff1a 封装Request和Response对象 xff0c 返回html静态资源文件 封装Request对象 想要封
  • 三.手写迷你版Tomcat-minicat3.0

    minicat 1 0我们实现了返回固定的字符串 34 Hello minicat 34 minicat 2 0封装Request和Response对象 xff0c 返回html静态资源文件 minicat 3 0需求 xff1a 请求se
  • python爬取全国五级行政区

    以前爬过国家统计局的四级行政区 xff08 http www stats gov cn tjsj tjbz tjyqhdmhcxhfdm 2017 xff09 xff0c 但是对于五级数据效果不是很好 偶然间发现这个网站 xff1a htt
  • ElasticSearch使用elasticsearchTemplate聚合查询

    这两天正好做个需求 xff0c 需要用到聚合查询 前几篇文章只是简单的提到过 xff0c 并没有真正的运用到实际产出中 xff0c 本篇结合实际代码 xff0c 专项学习ES的聚合查询 1 业务背景 有一张地址索引表 xff1a hisAd