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:9280
    username: xxxx
    password: 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:9280
    username: xxxx
    password: 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 {
    @Autowired
    RestHighLevelClient 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;
    }
}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

arXiv AI 综述列表(2024.05.20~2024.05.24)

公众号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 每周末更新&#xff0c;完整版进群获取。 Q 群在群文件&#xff0c;VX 群每周末更新。 目录 1. Beyond Traditional Single Object Tracking: A …

OSPF减少LSA更新量1

OSPF的LSA优化 一、汇总——优化骨干区域 (1)域间汇总ABR设备基于某个区域的1/2类LSA计算所得的最佳路由&#xff0c;共享给其他区域时&#xff0c;进行汇总传递。 [r2]ospf 1 [r2-ospf-1]area 1——明细路由所在区域&#xff0c;该ABR设备必须和明细路由在同一区域 [r2-ospf…

flink程序本地运行报: A JNI error has occurred和java.lang.NoClassDefFoundError

1.问题描述 在idea中运行flink job程序出现如下错误&#xff1a; Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/flink/api/common/io/FileInputFormat …

再见PS,Canva Create正式上线

再见&#xff0c;Photoshop&#xff01; Canva Create 正式上线&#xff0c;太疯狂了&#xff01;&#xff01; Canva是一款著名的免费在线AI图像生成器 构想你的创意&#xff0c;然后将其添加到你的设计中。使用最佳的AI图像生成器&#xff0c;观察你的文字和短语变换成美丽…

关于搜索引擎链路

一、搜索引擎的的链路 简单流程如下&#xff0c;一般都包括query理解&#xff0c;召回&#xff0c;粗排&#xff0c;精排&#xff0c;重排。 二、query理解&#xff0c;查询词处理 对于进来的query需要有很多道工序做处理。才能让搜索引擎的效果更好、更智能。 2.1 分词 分词…

OrangePi AIpro 开箱初体验及语音识别样例

OrangePi AIpro 开箱初体验及语音识别样例 一、 前言 首先非常感谢官方大大给予这次机会&#xff0c;让我有幸参加此次活动。 OrangePi AIpro联合华为精心打造&#xff0c;采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;…

Lin网络一:DHCP与FTP

目录 1、了解DHCP服务 2、使用DHCP服务有哪些好处 3、DHCP的分配方式 4、DHCP的租约过程 客户机请求IP地址 服务器确定租约 重新登陆 上述总结 配置&#xff1a; 5、传输文件到Linux服务器的常用工具: 1、FTP 文件传输协议 2、FTP传输模式&#xff1a; 3、FTP控制…

maven的下载以及配置的详细教程(附网盘下载地址)

文章目录 下载配置IDEA内部使用配置 下载 1.百度网盘下载 链接: https://pan.baidu.com/s/1LD9wOMFalLL49XUscU4qnQ?pwd1234 提取码: 1234 2.解压即可 配置 1.打开安装文件下conf下的settings.xml文件&#xff0c;我的如下 2.修改配置信息&#xff08;目的是为了修改本地…

Linux 磁盘管理命令tune2fs mkisofs cfdisk sfdisk parted

文章目录 3.Linux 磁盘管理命令3.26 tune2fs:文件系统调整案例练习 3.27 mkisofs:建立ISO9660 映象文件案例练习 3.28 cfdisk:磁盘分区案例练习 3.29 sfdisk:硬盘分区工具程序案例练习 3.30 parted:磁盘分区工具案例练习 3.Linux 磁盘管理命令 3.26 tune2fs:文件系统调整 作用…

汇编:比较跳转

在16位汇编语言&#xff08;如x86汇编&#xff09;中&#xff0c;比较指令用于比较两个操作数的大小&#xff0c;通常用于条件跳转、循环控制等逻辑操作&#xff0c;比较指令&#xff08;如CMP&#xff09;会根据操作数的比较结果设置标志寄存器中的相关标志位 比较指令影响的…

深入理解布瑞克(break)逻辑与嵌套循环的奥秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;布瑞克逻辑是什么&#xff1f; 二、布瑞克逻辑在嵌套循环中的应用 1.…

倩女幽魂手游攻略:赚银搬砖干货分享,轻松从0开始!

在倩女幽魂手游中&#xff0c;搬砖是许多玩家用来赚取银两和其他资源的主要方式之一。通过完成各种任务、参与活动以及合理利用市场交易&#xff0c;玩家可以积累大量的财富。以下是详细的搬砖攻略&#xff0c;帮助你在游戏中获得更多收益。 一、日常搬砖任务 日常任务 每天的…

找不到vcruntime140.dll等140dll的解决方法,怎么才能快速的修复?

找不到vcruntime140.dll等140dll要怎么办&#xff1f;以上这两个其实都是属于dll文件来的&#xff0c;它们的缺失会导致某些程序直接运行不了&#xff0c;你需要重新的进行修复&#xff0c;然后程序才可以运行下去&#xff0c;下面一起来了解一下找不到vcruntime140.dll等140dl…

深度神经网络——什么是自动编码器?

自动编码器 自动编码器&#xff08;Autoencoders&#xff09;是无监督学习领域中一种重要的神经网络架构&#xff0c;它们主要用于数据压缩和特征学习。 自动编码器的定义&#xff1a; 自动编码器是一种无监督机器学习算法&#xff0c;它通过反向传播进行训练&#xff0c;目标…

二叉树尾部分

1.二叉树的销毁 2.二叉树的层序遍历 3.判断二叉树是否为完全二叉树 4.二叉树的性质 1.二叉树的销毁 以后序的方式遍历销毁左右子数&#xff0c;因为前序和中序销毁的话根会被销毁而找不到左右子树的位置&#xff0c;后序的根访问在最后&#xff0c;可以找到左右的子树位置。…

基于C#开发web网页管理系统模板流程-主界面管理员录入和编辑功能完善

前言 紧接上篇->基于C#开发web网页管理系统模板流程-登录界面和主界面_c#的网页编程-CSDN博客 已经完成了登录界面和主界面&#xff0c;本篇将完善主界面的管理员录入和编辑功能&#xff0c;事实上管理员录入和编辑的设计套路适用于所有静态表的录入和编辑 首先还是介绍一下…

声学特征在膝关节健康诊断中的应用分析

关键词&#xff1a;膝关节声发射、膝关节生物标志物、因果关系、机器学习 声学膝关节健康评估长期以来一直被看作是一种替代临床可用医学成像工具的替代方法&#xff0c;如声发射技术是通过检测膝关节在运动过程中产生的微小裂纹或损伤引起的声波信号&#xff0c;从而评估关节的…

学习Uni-app开发小程序Day17

今天开始&#xff0c;就把uni-app前期使用的全部学完了&#xff0c;现在就把以前学习的&#xff0c;做成一案例&#xff0c;中间有未讲的&#xff0c;在进行补充&#xff0c;这里是根据老师视频进行项目案例编写的。 先弄出效果图&#xff0c;然后在根据效果图进行代码的编辑 …

linux 中 fd 申请和释放管理(两级 bitmap)

linux 中 fd 的几点理解_linux fd-CSDN博客 通过上边的文章&#xff0c;我们可以知道&#xff0c;在 linux 中&#xff0c;fd 有以下几点需要了解&#xff1a; &#xff08;1&#xff09;fd 表示进程打开的文件&#xff0c;是进程级别的资源&#xff0c;不是系统级别的资源 …

【鱼眼镜头11】Kannala-Brandt模型和Scaramuzza多项式模型区别,哪个更好?

Kannala-Brandt模型和Scaramuzza多项式模型在描述鱼眼相机畸变时都有其特定的数学表示和应用&#xff0c;但它们之间存在一些区别。以下是对两者区别的分点表示和归纳&#xff1a; 数学表示&#xff1a; Kannala-Brandt模型&#xff1a;它假设图像光心到投影点的距离和角度的多…