springboot 集成 es--未完结

基于es7.10.x版本

一、前提知识

常见的两种方式:spring boot提供的APIES 官方提供的API

  • ES官方:

    RestHighLevelClient
    适用于复杂、更细粒度控制的Elasticsearch 操作

  • spring boot:
    ElasticsearchRestTemplate:比 RestHighLevelClient 抽象更高,更接近于 Spring Data 的风格,当你想利用 Spring Data 的特性(如查询方法、分页等)与 Elasticsearch 交互时,这是一个很好的选择,但有些复杂查询无法完成。
    ElasticsearchRepository:抽象级别最高,隐藏了与 Elasticsearch 交互的底层细节,并提供了基于方法的查询功能,能够快速实现 CRUD 操作。

建议使用RestHighLevelClient
原因:
版本:ElasticsearchRestTemplate本身与spring-boot-starter-data-elasticsearch紧密依赖。如果想升级ElasticsearchRestTemplate,那就必须连带升级项目的Springboot版本,这个风险就比较高了,一般项目的Springboot版本不会轻易升级
灵活度:比较灵活,可以直接使用ES的DSL语法,实现复杂查询,同时没有与其他部件绑定,所以版本可以自由选择。,由于ElasticsearchRestTemplate是spring-boot-starter-data-elasticsearch封装的工具类,虽然使用上稍微方便一些,但是失去了灵活性,出现问题时也不易排查。

二、环境搭建

1、es 官方

RestHighLevelClient 方式

        <dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.10.0</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.10.0</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.10.0</version></dependency>
spring:elasticsearch:uris: http://172.31.97.4:9280username: xxxxpassword: xxxx

2、springdata

ElasticsearchRestTemplate+ElasticsearchRepository 方式

首先springdata操作es必须要将版本号和es的版本号对应上,否则会报错(倒不用完全一一对应,但版本号最好不要相差太多)。springdata引入的版本号由springboot的版本号决定,对应关系如下:
在这里插入图片描述

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>
spring:elasticsearch:uris: http://172.31.97.4:9280username: xxxxpassword: xxxx

二、API方法

1、es 官方
工工具类

package com.wang.service;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.query.AbstractQueryBuilder;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author Spider Man* @date 2024-05-23 15:15*/
@Component
@Slf4j
public class ESUtils {@AutowiredRestHighLevelClient esHighLevelClient;/*** 获取总条数** @param indexName* @return* @throws IOException*/public long getTotalNum(String indexName) throws IOException {CountRequest countRequest = new CountRequest(indexName);// 如果需要,你可以在这里添加查询条件// countRequest.query(QueryBuilders.matchQuery("field_name", "value"));CountResponse countResponse = esHighLevelClient.count(countRequest, RequestOptions.DEFAULT);return countResponse.getCount();}/*** 获取总页数** @param totalNum* @param limit* @return*/public int getTotalPage(long totalNum, int limit) {//总页数return (int) Math.ceil((double) totalNum / limit);}/*** 批量插入数据** @param indexName* @param list* @return boolean*/public boolean multiAddDoc(String indexName, List<JSONObject> list) {try {BulkRequest bulkRequest = new BulkRequest();list.forEach(doc -> {String source = JSONUtil.toJsonStr(doc);IndexRequest indexRequest = new IndexRequest(indexName);indexRequest.source(source, XContentType.JSON);bulkRequest.add(indexRequest);});BulkResponse bulkResponse = esHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);if (bulkResponse.hasFailures()){log.error("批量插入失败,第一条错误原因为 {}",bulkResponse.getItems()[0].getFailureMessage());}else {log.info("批量插入成功,向索引 {} 中批量插入 {} 条数据", indexName, list.size());}return !bulkResponse.hasFailures();} catch (Exception e) {e.printStackTrace();}return false;}/*** 根据id更新文档,全部字段更新** @param indexName* @param docId* @param jsonObject* @return boolean*/public boolean updateDocAllFiled(String indexName, String docId, JSONObject jsonObject) {try {UpdateRequest updateRequest = new UpdateRequest(indexName, docId).doc(JSONUtil.toJsonStr(jsonObject), XContentType.JSON);UpdateResponse updateResponse = esHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);int total = updateResponse.getShardInfo().getTotal();log.info("更新文档的影响数量为{}", total);return total > 0;} catch (Exception e) {e.printStackTrace();}return false;}/*** 局部更新** @param indexName* @param map    key为文档的id,map为所要更新字段的字段名称和值* @return* @throws IOException*/public boolean updateDocSomeFiled(String indexName, Map<String,Map<String, Object>> map) throws IOException {if (CollUtil.isEmpty(map)) {log.info("局部更新数据不能为空");return false;}BulkRequest bulkRequest = new BulkRequest();map.forEach((docId, value) -> {UpdateRequest updateRequest = new UpdateRequest(indexName, docId);updateRequest.doc(value);bulkRequest.add(updateRequest);});if (CollUtil.isNotEmpty(bulkRequest.requests())) {BulkResponse bulkResponse = esHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);if (bulkResponse.hasFailures()) {log.error("更新失败====》" + bulkResponse.buildFailureMessage());return false;}return true;} else {return false;}}/*** 例如:*     TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("ethnic_code.keyword", "汉族");*      Map<String, Object> map = esUtils.conditionSearchBySelfQuery(index, 1, 60, "pat_name",*      termQueryBuilder, "age_year", SortOrder.ASC, null, true);*** 条件搜索分页** @param indexName  索引库* @param pageNum    起始页* @param pageSize   每页大小* @param highName   高亮字段* @param abstractQueryBuilder   搜索条件* @param sortName   排序字段* @param sortOrder  排序类型* @param includes   显示的字段* @param isShowDocumentId  是否显示文档id* @return* @throws IOException*/public Map<String, Object> conditionSearchBySelfQuery(String indexName, Integer pageNum, Integer pageSize, String highName, AbstractQueryBuilder abstractQueryBuilder, String sortName, SortOrder sortOrder, String[] includes, boolean isShowDocumentId) throws IOException {SearchRequest searchRequest = new SearchRequest(indexName);//构造搜索条件SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.fetchSource(includes, null);if (sortName != null && sortOrder != null) {sourceBuilder.sort(sortName, sortOrder);}sourceBuilder.query(abstractQueryBuilder);//高亮处理if (!StrUtil.isEmpty(highName)) {buildHighlight(sourceBuilder, highName);}//分页处理if (pageNum != null && pageSize != null) {sourceBuilder.from(pageSize * (pageNum - 1));sourceBuilder.size(pageSize);}//超时设置sourceBuilder.timeout(TimeValue.timeValueSeconds(60));System.out.println("DSL语句为:\n"+sourceBuilder);searchRequest.source(sourceBuilder);//执行搜索SearchResponse searchResponse = esHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);SearchHits searchHits = searchResponse.getHits();List<JSONObject> resultList = new ArrayList<>();for (SearchHit hit : searchHits) {//原始查询结果数据Map<String, Object> sourceAsMap = hit.getSourceAsMap();if (isShowDocumentId) {sourceAsMap.put("_id", hit.getId());}//高亮处理if (!StrUtil.isEmpty(highName)) {Map<String, HighlightField> highlightFields = hit.getHighlightFields();HighlightField highlightField = highlightFields.get(highName);if (highlightField != null) {Text[] fragments = highlightField.fragments();StringBuilder value = new StringBuilder();for (Text text : fragments) {value.append(text);}sourceAsMap.put(highName, value.toString());}}JSONObject jsonObject = JSONUtil.parseObj(JSONUtil.toJsonStr(sourceAsMap));resultList.add(jsonObject);}long total = searchHits.getTotalHits().value;Map<String, Object> pageMap = new HashMap<>();if (pageNum != null && pageSize != null) {//当前页pageMap.put("pageNum", pageNum);//每页显示条数pageMap.put("pageSize", pageSize);//总页数pageMap.put("totalPage", total == 0 ? 0 : (int) (total % pageSize == 0 ? total / pageSize : (total / pageSize) + 1));}//总条数pageMap.put("totalNum", total);//数据pageMap.put("data", resultList);return pageMap;}/*** 构建高亮字段** @param sourceBuilder* @param highName*/private void buildHighlight(SearchSourceBuilder sourceBuilder, String highName) {HighlightBuilder highlightBuilder = new HighlightBuilder();//设置高亮字段highlightBuilder.field(highName);//多个高亮显示highlightBuilder.requireFieldMatch(false);//高亮标签前缀highlightBuilder.preTags("<span style='color:red'>");//高亮标签后缀highlightBuilder.postTags("</span>");sourceBuilder.highlighter(highlightBuilder);}/*** 根据id删除** @param indexName* @param id*/public void deleteById(String indexName, String id) {DeleteRequest deleteRequest = new DeleteRequest(indexName).id(id);try {DeleteResponse deleteResponse = esHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);if (deleteResponse.status().getStatus() != RestStatus.OK.getStatus()) {log.error(">>>> 删除id={}数据失败,返回状态码={} <<<<", id, deleteResponse.status().getStatus());}} catch (IOException e) {log.error(">>>> 删除数据发生异常,id={},异常信息={} <<<<", id, e.getMessage());}}/*** 根据id查询** @param indexName* @param id* @return*/public Map<String, Object> queryById(String indexName, String id) {GetRequest getRequest = new GetRequest(indexName).id(id);Map<String, Object> map = null;try {GetResponse getResponse = esHighLevelClient.get(getRequest, RequestOptions.DEFAULT);map = getResponse.getSource();} catch (IOException e) {e.printStackTrace();}return map;}/*** 判断索引是否存在** @param indexName 索引名称* @return* @throws IOException*/public boolean indexIsExists(String indexName) throws IOException {GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);return esHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);}public boolean createIndex(String indexName, Map<String, Object> propertyMap) throws IOException {boolean flag = false;if (!indexIsExists(indexName)) {try {CreateIndexRequest index = new CreateIndexRequest("index_name");Map<String, Object> properties = new HashMap<>();Map<String, Object> propertie = new HashMap<>();propertie.put("type", "text");propertie.put("index", true);propertie.put("analyzer", "ik_max_word");properties.put("field_name", propertie);XContentBuilder builder = JsonXContent.contentBuilder();builder.startObject().startObject("mappings").startObject("index_name").field("properties", properties).endObject().endObject().startObject("settings").field("number_of_shards", 3).field("number_of_replicas", 1).endObject().endObject();index.source(builder);esHighLevelClient.indices().create(index, RequestOptions.DEFAULT);flag = true;} catch (IOException e) {e.printStackTrace();throw new RuntimeException("创建索引和映射关系失败");}}return flag;}
}

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

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

相关文章

【无标题】MySQL基础命令

好的&#xff0c;以下是15个常见的MySQL命令及其解释&#xff1a; ### 1. 连接到MySQL服务器 sql mysql -u username -p - **解释**&#xff1a;使用指定的用户名连接到MySQL服务器&#xff0c;-p表示需要输入密码。 ### 2. 显示数据库列表 sql SHOW DATABASES; - **解释**…

AI智能体研发之路-模型篇(四):一文入门pytorch开发

博客导读&#xff1a; 《AI—工程篇》 AI智能体研发之路-工程篇&#xff08;一&#xff09;&#xff1a;Docker助力AI智能体开发提效 AI智能体研发之路-工程篇&#xff08;二&#xff09;&#xff1a;Dify智能体开发平台一键部署 AI智能体研发之路-工程篇&#xff08;三&am…

C++ | Leetcode C++题解之第115题不同的子序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int numDistinct(string s, string t) {int m s.length(), n t.length();if (m < n) {return 0;}vector<vector<unsigned long long>> dp(m 1, vector<unsigned long long>(n 1));for (i…

[docker] docker 安全知识 - 镜像,port registry

[docker] docker 安全知识 - 镜像&#xff0c;port & registry 这是第一篇&#xff0c;安全部分还有一篇笔记就记完了 说实话&#xff0c;看完了要学的这些东西&#xff0c;感觉大多数安全问题都可以通过验证登录的合法性去解决 镜像 镜像的问题还是比较多的&#xff0…

Mybatis——入门

新建 idea 准备 数据库 create table user(id int unsigned primary key auto_increment comment ID,name varchar(100) comment 姓名,age tinyint unsigned comment 年龄,gender tinyint unsigned comment 性别, 1:男, 2:女,phone varchar(11) comment 手机号 ) comment 用…

C语言 | Leetcode C语言题解之第116题填充每个节点的下一个右侧节点指针

题目&#xff1a; 题解&#xff1a; struct Node* connect(struct Node* root) {if (root NULL) {return root;}// 从根节点开始struct Node* leftmost root;while (leftmost->left ! NULL) {// 遍历这一层节点组织成的链表&#xff0c;为下一层的节点更新 next 指针stru…

调整GIF图大小的方法是什么?分享4个

调整GIF图大小的方法是什么&#xff1f;在数字化时代&#xff0c;GIF以其独特的动图魅力&#xff0c;成为了网络交流中不可或缺的一部分。无论是社交媒体、博客文章还是工作汇报&#xff0c;一个恰到好处的GIF图往往能有效吸引观众的注意&#xff0c;传递信息&#xff0c;但过大…

【YOLOv8改进[Neck]】小目标遮挡检测的性能提升(SEAM、MultiSEAM)- 目标遮挡检测(本文包含代码 + 修改方式等全部内容)

目录 一 SEAM 和 Repulsion Loss 1 SEAM 2 MultiSEAM 3 排斥损失Repulsion Loss 二 使用SEAM和 MultiSEAM改进YoloV8

File类.Java

一、File类 1&#xff0c;概述&#x1f3c0;&#x1f3c0;&#x1f3c0; &#xff08;1&#xff09; java.io.File类&#xff1a;文件和文件目录路径的抽象表示形式&#xff0c;与平台无关 &#xff08;2&#xff09; File类中涉及到关于文件或文件目录的创建、删除、重命…

Golang | Leetcode Golang题解之第115题不同的子序列

题目&#xff1a; 题解&#xff1a; func numDistinct(s, t string) int {m, n : len(s), len(t)if m < n {return 0}dp : make([][]int, m1)for i : range dp {dp[i] make([]int, n1)dp[i][n] 1}for i : m - 1; i > 0; i-- {for j : n - 1; j > 0; j-- {if s[i] …

对k8s 中etcd 存储进行备份和恢复操作

一. 安装 etcdctl 前面的步骤已经描述了如何安装 etcdctl&#xff0c;这里只做简要回顾&#xff1a; 下载 etcd&#xff1a; wget https://github.com/etcd-io/etcd/releases/download/v3.5.4/etcd-v3.5.4-linux-amd64.tar.gz解压缩&#xff1a; tar -xvf etcd-v3.5.4-linux-a…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(十七)- JUC(3)

目录 synchronized 面向对象改进 synchronized加在方法上 线程八锁 synchronized 线程1上锁之后&#xff0c;线程2无法获取锁不能够执行临时区&#xff0c;线程2阻塞等待线程1完成释放锁之后才能够使用。可以把synchronize类比成一个房间&#xff0c;每次有锁的人才能够进入…

Linux基础 (十一):进程间通信

Linux进程间通信&#xff08;Inter-Process Communication, IPC&#xff09;是指在不同进程之间交换数据或信息的机制。由于进程间不能直接共享内存&#xff0c;Linux 提供了多种 IPC 机制来实现进程间的通信。主要为&#xff1a;管道、信号量、共享内存、消息队列、套接字。 目…

C++三方库编译之GCC11.3.0

本系列准备持续更新&#xff0c;目的是将网上开源的三方库的编译过程与步骤&#xff0c;无脑展示&#xff0c;内容纯执行脚本与代码&#xff0c;不讲原理&#xff0c;也不科普库。 三方库编译很简单的(三板斧&#xff1a;configuremakeinstall)&#xff0c;为啥还需要整理&…

[Cesium学习]

底图切换 Cesium之底图切换_cesium地图切换-CSDN博客 ImageryProvider Cesium中比例尺设置 cesium给地图添加比例尺学习踩坑记录_cesium 比例尺-CSDN博客 webpack与less-loader版本对应问题 报错this.getOptions is not a function at Object.lessLoader”指的是在使用we…

halcon 传统缺陷检测

一、电路检测 算子解释 dyn_threshold *dyn_threshold 利用局部阈值分割图像*OrigImage (input_object)&#xff1a;原始图像*ThresholdImage (input_object)&#xff1a;处理后图像&#xff08;一般采用滤波处理&#xff09;*RegionDynThresh (output_object)&#xff1…

操作系统 - 文件管理

文件管理 考纲内容 文件 文件的基本概念&#xff1b;文件元数据和索引节点(inode) 文件的操作&#xff1a;建立&#xff0c;删除&#xff0c;打开&#xff0c;关闭&#xff0c;读&#xff0c;写 文件的保护&#xff1b;文件的逻辑结构&#xff1b;文件的物理结构目录 目录的基…

在Android系统中运行i2c tools

步骤 安装交叉编译工具 验证是否安装arm-none-eabi-gcc: arm-none-eabi-gcc -v安装&#xff1a;sudo apt install gcc-arm-none-eabi 安装 i2c-tools 下载i2c-tools源码: https://www.kernel.org/pub/software/utils/i2c-tools/ 编译 查看当前cpu架构:adb shell getprop r…

辅助驾驶ADAS功能算法介绍

一、ADAS功能分类 按照行驶域划分,将ADAS功能分为行车功能、泊车功能和主动安全功能。 行车功能 ACC(Adaptive Cruise Control)自适应巡航控制TJA(Traffic Jam Assist)交通拥堵辅助LCC(Lane Centering Control)车道居中控制ICC(Integration Cruise Control)智能巡航系…

const指针,星号判断方法

一 示例代码 1. const char *p // 指向常量的指针 2. char const *p // 指向常量的指针 3. char * const p // 指针常量二 判断方法 const在星号左边&#xff0c;指向常量的指针&#xff0c;指针p可修改。 const在星号右边&#xff0c;指针常量&#xff0c;指针p不可修改。