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,一经查实,立即删除!

相关文章

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;但过大…

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] …

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

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

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;文件的物理结构目录 目录的基…

英语学习笔记24——Give me/us/him/her/them some ...

Give me/us/him/her/them some … 给我/我们/他/她/他们一些…… 词汇 Vocabulary desk n. 课桌&#xff08;有书桌堂&#xff09;&#xff0c;写字台 复数&#xff1a;desks 搭配&#xff1a;desk mate 同桌    构成&#xff1a;desk mate 桌子上的伙伴 同桌    cl…

[Algorithm][动态规划][简单多状态DP问题][买卖股票的最佳时机 III][买卖股票的最佳时机 Ⅳ]详细讲解

目录 1.买卖股票的最佳时机 III1.题目链接2.算法原理详解3.代码实现 2.买卖股票的最佳时机 IV1.题目链接2.算法原理详解3.代码实现 1.买卖股票的最佳时机 III 1.题目链接 买卖股票的最佳时机 III 2.算法原理详解 注意&#xff1a;本题为了便于初始化&#xff0c;有较多细节服…

瑞萨RA8系列教程 | 基于e2s实现RA8串口输出配置

关注星标公众号&#xff0c;不错过精彩内容 作者 | strongerHuang 微信公众号 | strongerHuang 串口是最常见的通信方式之一&#xff0c;也是单片机调试最常见的通信接口&#xff0c;也是现在的单片机必备的通信接口&#xff0c;目前&#xff08;2024-05&#xff09;最新、最强…

【香橙派AIpro】开箱测评

1.板子开箱 哟&#xff0c;看起来还不错哦&#xff01;&#xff01;&#xff01; 收货清单&#xff1a; 主板*1 1.5m数据线*1 充电头*1 1.1.充电头 近65W的充电头&#xff0c;不错不错。 1.2.主板 1.2.1.上面 哇噢&#xff0c;还送了2.4/5G的WiFi和蓝牙天线。 emm&#xf…

卷出新高度,直呼太强!时隔三月,YOLO再度进化升级:《YOLOv10—实时端到端目标检测》重磅来袭

真的是不止一次感叹&#xff0c;学习的速度都跟不上发论文出新品的速度。。。。。 继前文YOLOv9发布以来也就不到三个月的时间&#xff0c;YOLOv10就来了&#xff01; 《太卷了&#xff0c;目标检测新成员——YOLOv9: Learning What You Want to LearnUsing Programmable Gra…

吴恩达2022机器学习专项课程C2W2:2.22 多类 softmax softmax与神经网络 softmax的代码改良 多标签分类

目录 多分类问题1.什么是多分类问题2.多分类问题案例3.二分类与多分类的区别 Softmax1. 什么是Softmax2.逻辑回归预测的计算过程3. Softmax预测的计算过程4.Softmax 回归与逻辑回归的关系5. Softmax的损失函数 softmax与神经网络1.设置Softmax层2.Softmax层的计算3.softmax激活…

卸载/删除 Maxask.com,最简单的方法

被绑架的浏览器&#xff0c;太恶心了。 Maxask伪装成了插件&#xff0c;在你搜索网页的时候利用了重定向&#xff0c;导致出现的界面时Maxask的界面&#xff0c;很恶心。 只需要排查正在使用的&#xff0c;如下图有颜色的图表。 删除一个插件&#xff0c;浏览器搜索一下看看有…

mysql数据库安装指南

这里写自定义目录标题 官网下载mysql数据库安装MySQL数据库添加环境变量查看mysql的服务验证是否配置成功 注意&#xff1a;如果用MySQL8的版本安装不成功&#xff0c;可以尝试用MySQL5的版本。MySQL8的版本可能在windows上一直不能启动&#xff0c;经过查询是某个版本的漏洞。…

知识存储概述

文章目录 知识存储概述知识存储方式知识存储基础工具技术发展趋势 知识存储是针对知识图谱的知识表示形式设计底层存储方式&#xff0c;完成各类知识的存储&#xff0c;以支持对大规模图数据的有效管理和计算。知识存储的对象包括基本属性知识、关联知识、事件知识、时序知识和…