ES在企业项目中的实战总结,彻底掌握ES的使用

news2025/2/26 19:11:45

通过之前两篇文章

  • 了解了ES的核心概念和基础使用
  • 学习进阶的DSL语法处理复杂的查询

这段时间通过在本企业代码中对ES框架的使用,总结了不少经验。主要分为三点

  • 企业封装了ES原生的api,需要使用企业项目提供的接口实现 -------简单使用(本章节目的)
  • 项目会遇到更复杂的查询需求,需要进一步深入对ES的学习 -------复杂使用
  • 了解项目如何封装原生的api,学习设计思想 --------深入学习

目录

  • 1. Term查询
    • 1.1 原生api实现term查询
    • 1.2 企业api实现term查询
  • 2. 复合查询__must
    • 2.1 原生api实现must查询
    • 2.2 企业api实现must查询
  • 3. 复合查询__should
  • 4. 复合查询__mustnot
  • 5. 分页和排序
    • 5.1 原生api实现分页和排序
    • 5.2 企业api实现分页和排序
  • 6 聚合查询
    • 6.1 原生api实现桶聚合
    • 6.2 企业api实现桶聚合

------------------------------本章节核心目的是梳理出 本企业项目提供的api原生ES提供的api 的使用区别--------------------------------





本企业将ES的api大致封装成了两个核心类
EsOperater类

方法说明
String[] indexes()
Integer from()分页
Integer size()分页
List sort()排序
QueryBuilder queryBuilder()普通查询/复合查询
EsOperaterBuiler esOperaterBuiler()继承类
SearchResponse execute()执行查询
CountResponse queryTotal()
SearchResponse executeScroll()
QueryBuilder buildQueryBuilder()
QueryBuilder buildQueryBuilderByQueryType(EsQueryInfoBean queryInfo)根据查询信息bean构造相应的查询器
List buildAggBuilder()根据aggMap创建聚合器,包括单层聚合和多层聚合
AggregationBuilder makeChildAgg(EsAggInfoBean esAggInfo, EsAggInfoBean parentAggInfo)递归创建聚合器
EsOperater build()

EsOperaterBuiler类(重点关注)

方法说明
EsOperaterBuiler indexes(String… indexes)设置索引集合
EsOperaterBuiler from(Integer from)设置分页参数的查询数量
EsOperaterBuiler size(Integer size)设置分页参数的查询数量
EsOperaterBuiler sort(String sort)设置排序字段
EsOperaterBuiler sortOrder(SortOrder sortOrder)设置排序排序方式(升序、降序)
EsOperaterBuiler queryBuilder(QueryBuilder queryBuilder)设置查询构建器(QueryBuilder),如果操作构建器(EsOperater)中buildQueryBuilder()方法构造不出需要的查询构建起,
Boolean isAliasExists(String indexName)查询别名是否存在

1. Term查询

1.1 原生api实现term查询

@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
    // 2. 构建DSL
    	// 2.1 获取建造者
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		// 2.2 建造者调用DSL
    searchSourceBuilder.termQuery("name","zjh");
    	// 2.3 组装
    request.source(searchSourceBuilder);
  
    	// 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    	// 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

此时就可以获取到source的数据了。上述写法也可以简化,如下

// 此方式常用
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	// 2. 构建DSL语句
    request.source().query(QueryBuilders.termQuery("name","zjh"));
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

1.2 企业api实现term查询

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 设置查询构建器 + 准备DSL语句
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

解释:

步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤二:需要将 DSL语句 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response

2. 复合查询__must

2.1 原生api实现must查询

@Test
void MustQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	// 2. 构建DSL语句
    	// 2.1 创建bool查询
    	BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    	// 2.2 添加must条件
        boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
 		// 2.3 构建请求内容
   		request.source().query(boolQuery);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

2.2 企业api实现must查询

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 设置查询构建器 + 准备DSL语句
    	// 2.1 创建bool查询
    	BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    	// 2.2 添加must条件
        boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    	// 此行代码的作用就是将构造的must条件,存放到EsOperater类的全局变量
    	builder.queryBuilder(boolQuery);
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}
解释一下步骤二:
    可能会疑惑为什么不这样写
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    BoolQueryBuilder mustQuery = boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    builder.queryBuilder(mustQuery);

	因为must(参数)底层会将参数传给boolQuery.must()的boolQuery对象,是递增的逻辑

解释:

步骤一:需要将 索引名 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤二:需要将 DSL语句(布尔查询) 存到 esOperaterBuiler类 的全局变量中,以便其他方法调用

步骤三:需要从esOperaterBuiler类 切换到 esOperater类,再执行最核心的 execute() 方法,这个方法会进行一些列操作,将最终的结果返回给 response

可以进一步简化

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // DSL语句
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    boolQuery.must(QueryBuilders.termQuery("name", "zjh"));
    
    // 使用企业api实现查询
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler();
    
    SearchResponse response = builder.index(indexName).queryBuilder(boolQuery).build().execute();
   
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

3. 复合查询__should

同理

4. 复合查询__mustnot

同理

5. 分页和排序

5.1 原生api实现分页和排序

// 此方式常用
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
		//2.查询__构建DSL语句
    	request.source().query(QueryBuilders.termQuery("name","zjh"));
    
    	//  分页
    	request.source().from.size(5);
    
    	//  时间排序
    	request.source().sort(“logTime”,SortOrder.ASC);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }
    
}

5.2 企业api实现分页和排序

@Test
void TermQuery(){
    // 构建索引名称
    String indexName = ElasticSearchConst.UNSTRUCTURE_FILE_SCAN_RESULT + taskId;
    
    // 1. 设置索引集合
    EsOperater.EsOperaterBuiler builder = EsOperater.esOperaterBuiler().indexes(indexName);
    
    // 2. 查询
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh"));
    
    //  分页
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).size(5);
    
    //  排序
    builder.queryBuilder(QueryBuilders.termQuery("name","zjh")).sort("logTime").sortOrder(SortOrder.DESC);
    
    // 3. 发送请求
    SearchResponse response = builder.build().execute();
    
    //  4. 解析数据,得到_source数据
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
       System.out.println(hit.getSourceAsString());
     }

}

6 聚合查询

6.1 原生api实现桶聚合

// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	//2.查询
    	// CityName:自定义桶名; city:根据城市聚合
     	AggregationBuilder aggregationBuilder1 = AggregationBuilders.terms("CityName").field("city");
    	AggregationBuilder aggregationBuilder2 = AggregationBuilders.terms("BrandName").field("brand");
    	
    	request.source().aggregation(aggregationBuilder1);
    	request.source().aggregation(aggregationBuilder2);
    
    // 3. 发送请求
    SearchResponse reponse = client.search(request, RequestOptions.ESFAULT);
    
    // 4. 解析数据
    Aggreagtions aggreagtions = response.getAggreagtions();
    List<? extends Terms.Bucket> buckets1 =  aggreagtions.get("CityName").getBuckets();
    for (Terms.Bucket bucket : buckets) {
       //打印结果是:西安 或者 上海
       System.out.println(bucket.getKeyAsString());
     }
    
     List<? extends Terms.Bucket> buckets2 =  aggreagtions.get("BrandName").getBuckets();
    for (Terms.Bucket bucket : buckets) {
       //打印结果是:星巴克 或者 瑞幸
       System.out.println(bucket.getKeyAsString());
     }
    
}

6.2 企业api实现桶聚合

// 需求:实现对城市、品牌的聚合。即用户输入城市、品牌,得到搜索结果
@Test
void TermQuery(){
    // 获取client
    这里默认已经获取
        
    // 1. 准备request (参数为索引名称)
    SearchRequest request = new SearchRequest("indexName");
    
	//2.查询
   	List<AggregationBuilder> aggregationBuilderList = new ArrayList<>();
    aggregationBuilderList.add(AggregationBuilders.terms("CityName").field("city"));;
    aggregationBuilderList.add(AggregationBuilders.terms("BrandName").field("brand"));
    // aggBuilderList()企业封装的工具,将聚合参数赋值到全局变量上
    builder.aggBuilderList(aggregationBuilderList);

    
    // 3. 发送请求
    SearchResponse response = builder.size(1).build().execute();
    
    // 4. 解析数据
    Aggreagtions aggreagtions = response.getAggreagtions();
    // 注意ParsedStringTerms,还有ParsedLongTerms、ParsedDoubleTerms...
    ParsedStringTerms CityName =  aggreagtions.get("CityName");
    
    for (Terms.Bucket bucket : CityName.getBuckets()) {
       //打印结果是:西安 或者 上海
       System.out.println(bucket.getKeyAsString());
     }
    
    ParsedStringTerms BrandName =  aggreagtions.get("BrandName");
    for (Terms.Bucket bucket : BrandName.getBuckets()) {
       //打印结果是:星巴克 或者 瑞幸
       System.out.println(bucket.getKeyAsString());
     }
    
}

这里需要解释一下步骤四中的 ParsedStringTerms

ES会将聚合结果封装到特定的类中,方便你来处理不同类型的聚合结果。

ParsedLongTerms:

  • 这个类用于处理长整型(long)类型的聚合结果。

ParsedStringTerms:

  • 这个类用于处理字符串(String)类型的聚合结果。

什么意思呢?在ES中对"CityName"进行聚合。

返回结果中可以看到如下信息,表示星巴克有三家(西安)

  • key:“星巴克” (字符串类型)

  • doc_count : 3 (long类型)

因此根据key的类型,正确选择使用ParsedStringTerms || ParsedLongTerms ||…接收聚合结果,否则报错。

示例图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1126577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AutoDev 1.4 规模化 AI 研发辅助:团队 Prompts、自定义活文档、代码检视

在过去的两个月里&#xff0c;随着 Thoughtworks 内部的大规模 AI 辅助软件交付&#xff08;AI4SoftwareDelivery&#xff09;的展开 —— 在全球&#xff0c;有上千名的 Thoughtworker 这一个涉及不同角色、不同地区&#xff0c;以及几十场内部分享的活动。 我们也在 AutoDev …

【Leetcode】单链表 ---移除链表元素(创建虚拟头节点)

移除链表元素 移除链表元素题目思路图解创建虚拟头结点删除操作 代码 移除链表元素 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 题目思路 题目思路&#xff1a; …

acme.sh签发和部署ZeroSSL泛域名证书

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 介绍 acme.sh 是个开源的shell证书生成脚本&#xff0c;他可以自动生成Let’s Encrypt 的证书…

【Spring Cloud Alibaba】seata分布式事务官方入门案例导读1(实战版)

文章目录 1. 业务介绍1.1. 用例1.2. 架构图1.3. 3个服务的代码及业务逻辑&#xff08;略&#xff09; 2. SEATA 的分布式交易解决方案3. 由Dubbo SEATA提供支持的示例&#xff08;实战&#xff09;3.1. 步骤 1&#xff1a;建立数据库&#xff0c;如seata数据库3.2. 步骤 2&…

速锐得解码匹配特斯拉电动汽车安全性能检测车架号及BMS电池数据

电动汽车三大件分别是电池、电机和电控。到目前为止&#xff0c;电机技术已经非常成熟&#xff0c;直流永磁电机、永磁同步电机已经取代了异步电机&#xff0c;成为电动汽车的主流。很多人认为电动汽车最后一道技术门槛是电池&#xff0c;但在我国&#xff0c;汽车制造商在制造…

VMware虚拟机中ubuntu网络连接不上

VMware虚拟机中ubuntu中网络连接不上 解决方案其他虚拟机网络 解决方案 1.选择VMware中编辑-虚拟网络编辑器-更改&#xff1a; 设置为你喜欢的模式&#xff0c;这里为NET模式 2.选中ubuntu虚拟机&#xff08;关机后的虚拟机&#xff09;&#xff0c;点击&#xff1a;编辑虚拟机…

微信视频号的项目玩法,视频号好物分享,只要你会剪辑,就可以去操作

今天我给大家分享一个超有趣的项目玩法——视频号好物分享&#xff01; 你知道吗&#xff0c;不论是在抖音还是快手、小红薯&#xff0c;这类好物分享账号都是非常流行的。 不过&#xff0c;现如今这些账号已经不再只是简单的分享&#xff0c;而是有目的地进行推荐&#xff0c;…

【面试经典150 | 哈希表】快乐数

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;哈希集合判重方法二&#xff1a;快慢指针判重 其他语言python3 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为…

【COMP305 LEC6 LEC 7】

LEC 6 Topic 2. The McCulloch-Pitts Neuron (1943) 1. What kind of propositions can be represented by a single MP neuron (without time)? OR&#xff1a; 中间那条线就是 a1 a2 1 分成了两半&#xff1a;1. on the line 和 above the line 2. below the line …

【计算机网络】NAT机制的工作流程

网络地址转换&#xff08;NAT&#xff09;是一种将私有IP地址转换为公共IP地址的技术&#xff0c;它使得私有网络中的主机可以在互联网上与外部主机进行通信。NAT机制在路由器或专用NAT设备上配置&#xff0c;可以用于家庭、小型企业或大型企业的网络环境中。本文将总结NAT机制…

flutter开发实战-打包应用apk签名及Android studio没有generate signed bundle/apk问题修改

flutter开发实战-打包应用apk签名及Android studio没有generate signed bundle/apk问题修改 最近使用flutter开发项目&#xff0c;需要将打包应用时候apk进行签名&#xff0c;我这边开发使用的是Android studio&#xff0c;发现在Android studio的build没有generate signed bu…

读高性能MySQL(第4版)笔记18_扩展MySQL

1. 增长 1.1. 在高速的业务环境中&#xff0c;流量可能逐年增长几个数量级&#xff0c;环境会变得更加复杂&#xff0c;随之而来的数据需求也会快速增加 1.2. 扩展Web服务器 1.2.1. 在负载均衡的后端添加更多的服务器节点&#xff0c;而这通常就是扩展We b服务器的全部工作 …

【银河麒麟系统】备份还原工具显示“备份分区空间不足,请删除过期或者不需要的备份”解决方法

一.问题的现象 在进行银行麒麟V10的系统备份时&#xff0c;会因为所需备份的系统过大导致备份分区容量不足导致备份失败的情况&#xff1a; 二.解决方法 该问题的处理思路与之前写过的一篇文章&#xff1a;【linux】把home目录挂载到其他分区&#xff08;数据盘/data等&#xf…

Day8力扣打卡

打卡记录 查找和替换模式&#xff08;哈希表 / find函数查询重复程度&#xff09; 链接 1.hash表双映射检测是否存在相同映射。 2.利用string的find函数返回下标来检测对应字符串的重复程度(妙)。 class Solution { public:vector<string> findAndReplacePattern(vect…

Web APIs——事件监听以及案例

1、事件监听 什么是事件&#xff1f; 事件是在编程时系统内发生的动作或者发生的事情 比如用户在网页上单击一个按钮 什么是事件监听&#xff1f; 就是让程序检测是否有事件产生&#xff0c;一旦有事件触发&#xff0c;就立即调用一个函数做出响应&#xff0c;也称为绑定事…

基于斑点鬣狗算法的无人机航迹规划-附代码

基于斑点鬣狗算法的无人机航迹规划 文章目录 基于斑点鬣狗算法的无人机航迹规划1.斑点鬣狗搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用斑点鬣狗算法来优化无人机航迹规划。 …

LiveGBS流媒体平台GB/T28181常见问题-海康大华宇视硬件NVR摄像头通道0未获取到视频通道如何排查如何抓包分析

LiveGBS常见问题海康大华宇视硬件NVR摄像头通道0未获取到视频通道如何排查如何抓包分析&#xff1f; 1、硬件NVR配置接入示例2、通道数为0处置2.1、判断信令是否畅通2.1.1、点击更新通道2.1.2、有成功提示2.1.2.1、确认设备的视频通道编码是否填写2.1.2.2、确认是否超过授权数目…

【ArcGIS模型构建器】03:多个shp批量按属性分割(多个县区批量提取乡镇)

文章目录 一、数据预览二、模型构建三、保存模型一、数据预览 加载实验数据: 本试验实现将两个县区的数据分割为乡镇数据。 二、模型构建 1. 添加数据文件夹 将县区数据所在的根目录文件夹拖进模型。 2. 添加要素类迭代器 插入→迭代器→要素类。 用连接工具,将数据文件…

【计算机网络笔记】网络应用的体系结构

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

【C++入门篇】保姆级教程篇【上】

目录 一、第一个C程序 二、C命名空间 1&#xff09;什么是命名空间&#xff1f; 2&#xff09;命名空间的使用 3&#xff09; std库与namespace展开 4&#xff09;命名空间的嵌套使用 三、输入输出方式 四、缺省参数 1&#xff09;什么是缺省参数&#xff1f; 2&#xff0…