SpringBoot3集成ElasticSearch

标签:ElasticSearch8.Kibana8;

一、简介

Elasticsearch是一个分布式、RESTful风格的搜索和数据分析引擎,适用于各种数据类型,数字、文本、地理位置、结构化数据、非结构化数据;

在实际的工作中,历经过Elasticsearch从6.07.0的版本升级,而这次SpringBoot3和ES8.0的集成,虽然脚本的语法变化很小,但是Java客户端的API语法变化很大;

二、环境搭建

1、下载安装包

需要注意的是,这些安装包的版本要选择对应的,不然容易出问题;

软件包:elasticsearch-8.8.2-darwin-x86_64.tar.gz
分词器工具:elasticsearch-analysis-ik-8.8.2.zip
可视化工具:kibana-8.8.2-darwin-x86_64.tar.gz

2、服务启动

不论是ES还是Kibana,在首次启动后,会初始化很多配置文件,可以根据自己的需要做相关的配置调整,比如常见的端口调整,资源占用,安全校验等;

1、启动ES
elasticsearch-8.8.2/bin/elasticsearch本地访问:localhost:92002、启动Kibana
kibana-8.8.2/bin/kibana本地访问:http://localhost:5601# 3、查看安装的插件
http://localhost:9200/_cat/plugins  ->  analysis-ik 8.8.2

三、工程搭建

1、工程结构

2、依赖管理

starter-elasticsearch组件中,实际上依赖的是elasticsearch-java组件的8.7.1版本;

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><version>${spring-boot.version}</version>
</dependency>

3、配置文件

在上面环境搭建的过程中,已经禁用了用户和密码的登录验证,配置ES服务地址即可;

spring:# ElasticSearch配置elasticsearch:uris: localhost:9200

四、基础用法

1、实体类

通过DocumentField注解描述ES索引结构的实体类,注意这里JsonIgnoreProperties注解,解决索引中字段和实体类非一一对应的而引起的JSON解析问题;

@JsonIgnoreProperties(ignoreUnknown = true)
@Document(indexName = "contents_index", createIndex = false)
public class ContentsIndex implements Serializable {private static final long serialVersionUID=1L;@Field(type= FieldType.Integer)private Integer id;@Field(type= FieldType.Keyword)private String title;@Field(type= FieldType.Keyword)private String intro;@Field(type= FieldType.Text)private String content;@Field(type= FieldType.Integer)private Integer createId;@Field(type= FieldType.Keyword)private String createName;@Field(type= FieldType.Date,format = DateFormat.date_hour_minute_second)private Date createTime;
}

2、初始化索引

基于ElasticsearchTemplate类和上述实体类,实现索引结构的初始化,并且将tb_contents表中的数据同步到索引中,最后通过ID查询一条测试数据;

@Service
public class ContentsIndexService {private static final Logger log = LoggerFactory.getLogger(ContentsIndexService.class);@Resourceprivate ContentsService contentsService ;@Resourceprivate ElasticsearchTemplate template ;/*** 初始化索引结构和数据*/public void initIndex (){// 处理索引结构IndexOperations indexOps = template.indexOps(ContentsIndex.class);if (indexOps.exists()){boolean delFlag = indexOps.delete();log.info("contents_index exists,delete:{}",delFlag);indexOps.createMapping(ContentsIndex.class);} else {log.info("contents_index not exists");indexOps.createMapping(ContentsIndex.class);}// 同步数据库表记录List<Contents> contentsList = contentsService.queryAll();if (contentsList.size() > 0){List<ContentsIndex> contentsIndexList = new ArrayList<>() ;contentsList.forEach(contents -> {ContentsIndex contentsIndex = new ContentsIndex() ;BeanUtils.copyProperties(contents,contentsIndex);contentsIndexList.add(contentsIndex);});template.save(contentsIndexList);}// ID查询ContentsIndex contentsIndex = template.get("10",ContentsIndex.class);log.info("contents-index-10:{}",contentsIndex);}
}

3、仓储接口

继承ElasticsearchRepository接口,可以对ES这种特定类型的存储库进行通用增删改查操作;在测试类中对该接口的方法进行测试;

// 1、接口定义
public interface ContentsIndexRepository extends ElasticsearchRepository<ContentsIndex,Long> {
}// 2、接口测试
public class ContentsIndexRepositoryTest {@Autowiredprivate ContentsIndexRepository contentsIndexRepository;@Testpublic void testAdd (){// 单个新增contentsIndexRepository.save(buildOne());// 批量新增contentsIndexRepository.saveAll(buildList()) ;}@Testpublic void testUpdate (){// 根据ID查询后再更新Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(14L);if (contentsOpt.isPresent()){ContentsIndex contentsId = contentsOpt.get();System.out.println("id=14:"+contentsId);contentsId.setContent("update-content");contentsId.setCreateTime(new Date());contentsIndexRepository.save(contentsId);}}@Testpublic void testQuery (){// 单个ID查询Optional<ContentsIndex> contentsOpt = contentsIndexRepository.findById(1L);if (contentsOpt.isPresent()){ContentsIndex contentsId1 = contentsOpt.get();System.out.println("id=1:"+contentsId1);}// 批量ID查询Iterator<ContentsIndex> contentsIterator = contentsIndexRepository.findAllById(Arrays.asList(10L,12L)).iterator();while (contentsIterator.hasNext()){ContentsIndex contentsIndex = contentsIterator.next();System.out.println("id="+contentsIndex.getId()+":"+contentsIndex);}}@Testpublic void testDelete (){contentsIndexRepository.deleteById(15L);contentsIndexRepository.deleteById(16L);}
}

4、查询语法

无论是ElasticsearchTemplate类还是ElasticsearchRepository接口,都是对ES常用的简单功能进行封装,在实际使用时,复杂的查询语法还是依赖ElasticsearchClient和原生的API封装;

这里主要演示七个查询方法,主要涉及:ID查询,字段匹配,组合与范围查询,分页与排序,分组统计,最大值查询和模糊匹配;更多的查询API还是要多看文档中的案例才行;

public class ElasticsearchClientTest {@Autowiredprivate ElasticsearchClient client ;@Testpublic void testSearch1 () throws IOException {// ID查询GetResponse<ContentsIndex> resp = client.get(getReq ->getReq.index("contents_index").id("7"), ContentsIndex.class);if (resp.found()){ContentsIndex contentsIndex = resp.source() ;System.out.println("contentsIndex-7:"+contentsIndex);}}@Testpublic void testSearch2 () throws IOException {// 指定字段匹配SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(query -> query.match(field -> field.field("createName").query("张三"))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch3 () throws IOException {// 组合查询:姓名和时间范围Query byName = MatchQuery.of(field -> field.field("createName").query("王五"))._toQuery();Query byTime = RangeQuery.of(field -> field.field("createTime").gte(JsonData.of("2023-07-10T00:00:00")).lte(JsonData.of("2023-07-12T00:00:00")))._toQuery();SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(query -> query.bool(boolQuery -> boolQuery.must(byName).must(byTime))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch4 () throws IOException {// 排序和分页,在14条数据中,根据ID倒序排列,从第5条往后取4条数据SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").from(5).size(4).sort(sort -> sort.field(sortField -> sortField.field("id").order(SortOrder.Desc))),ContentsIndex.class);printResp(resp);}@Testpublic void testSearch5 () throws IOException {// 根据createId分组统计SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").aggregations("createIdGroup",agg -> agg.terms(term -> term.field("createId"))),ContentsIndex.class);Aggregate aggregate = resp.aggregations().get("createIdGroup");LongTermsAggregate termsAggregate = aggregate.lterms();Buckets<LongTermsBucket> buckets = termsAggregate.buckets();for (LongTermsBucket termsBucket : buckets.array()) {System.out.println(termsBucket.key() + " : " + termsBucket.docCount());}}@Testpublic void testSearch6 () throws IOException {// 查询最大的IDSearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").aggregations("maxId",agg -> agg.max(field -> field.field("id"))),ContentsIndex.class);for (Map.Entry<String, Aggregate> entry : resp.aggregations().entrySet()){System.out.println(entry.getKey()+":"+entry.getValue().max().value());}}@Testpublic void testSearch7 () throws IOException {// 模糊查询title字段,允许1个误差Query byContent = FuzzyQuery.of(field -> field.field("title").value("设计").fuzziness("1"))._toQuery();SearchResponse<ContentsIndex> resp = client.search(searchReq -> searchReq.index("contents_index").query(byContent),ContentsIndex.class);printResp(resp);}private void printResp (SearchResponse<ContentsIndex> resp){TotalHits total = resp.hits().total();System.out.println("total:"+total);List<Hit<ContentsIndex>> hits = resp.hits().hits();for (Hit<ContentsIndex> hit: hits) {ContentsIndex contentsIndex = hit.source();System.out.println(hit.id()+":"+contentsIndex);}}
}

五、参考源码

文档仓库:
https://gitee.com/cicadasmile/butte-java-note源码仓库:
https://gitee.com/cicadasmile/butte-spring-parent

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

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

相关文章

科技云报道:算力之战,英伟达再度释放AI“炸弹”

科技云报道原创。 近日&#xff0c;在计算机图形学顶会SIGGRAPH 2023现场&#xff0c;英伟达再度释放深夜“炸弹”&#xff0c;大模型专用芯片迎来升级版本。 英伟达在会上发布了新一代GH200 Grace Hopper平台&#xff0c;该平台依托于搭载全球首款搭载HBM3e处理器的新型Grac…

从LeakCanary看ViewModel生命周期监控

前面两篇文章中已经了解了LeakCanary中Service和Fragment生命周期监控的实现&#xff0c;那么ViewModel生命周期监控又是怎么实现的呢&#xff1f; 同样的&#xff0c;要了解ViewModel生命周期监控&#xff0c;我们首先应该清楚在代码结构中ViewModel是如何存储获取的&#xf…

使用 Python 在 NLP 中进行文本预处理

一、说明 自然语言处理 &#xff08;NLP&#xff09; 是人工智能 &#xff08;AI&#xff09; 和计算语言学的一个子领域&#xff0c;专注于使计算机能够理解、解释和生成人类语言。它涉及计算机和自然语言之间的交互&#xff0c;允许机器以对人类有意义和有用的方式处理、分析…

SpringBoot代理访问本地静态资源400 404

SpringBoot代理访问静态资源400 404 背景&#xff1a;pdf文件上传到linux服务器上&#xff0c;使用SpringBoot代理访问问题&#xff1a;访问过程中可能会出现400、404问题 前提&#xff1a;保证有文件&#xff0c;并且文件路径正确 SpringBoot如何配置静态资源代理&#xff0…

[python] Kmeans文本聚类算法+PAC降维+Matplotlib显示聚类图像

0 前言 本文主要讲述以下几点&#xff1a; 1.通过scikit-learn计算文本内容的tfidf并构造N*M矩阵(N个文档 M个特征词)&#xff1b; 2.调用scikit-learn中的K-means进行文本聚类&#xff1b; 3.使用PAC进行降维处理&#xff0c;每行文本表示成两维数据&…

8 种主流数据迁移工具技术选型

前言 最近有些小伙伴问我&#xff0c;ETL数据迁移工具该用哪些。 ETL(是Extract-Transform-Load的缩写&#xff0c;即数据抽取、转换、装载的过程)&#xff0c;对于企业应用来说&#xff0c;我们经常会遇到各种数据的处理、转换、迁移的场景。 今天特地给大家汇总了一些目前…

pdf怎么合并在一起?这几个合并方法了解一下

pdf怎么合并在一起&#xff1f;在日常工作、学习和生活中&#xff0c;我们常常会遇到需要将多个PDF文件合并成一个文件的情况。比如&#xff0c;在学术论文写作中&#xff0c;我们可能需要将多篇论文合并成一个文件进行打印和提交。在工作中&#xff0c;我们可能需要将多个报告…

STM32——SPI外设总线

SPI外设简介 STM32内部集成了硬件SPI收发电路&#xff0c;可以由硬件自动执行时钟生成、数据收发等功能&#xff0c;减轻CPU的负担 可配置8位/16位数据帧、高位先行/低位先行 时钟频率&#xff1a; fPCLK / (2, 4, 8, 16, 32, 64, 128, 256) 支持多主机模型、主或从操作 可…

耕地单目标语义分割实践——Pytorch网络过程实现理解

一、卷积操作 &#xff08;一&#xff09;普通卷积&#xff08;Convolution&#xff09; &#xff08;二&#xff09;空洞卷积&#xff08;Atrous Convolution&#xff09; 根据空洞卷积的定义&#xff0c;显然可以意识到空洞卷积可以提取到同一输入的不同尺度下的特征图&…

excel常见的数学函数篇2

一、数学函数 1、ABS(number)&#xff1a;返回数字的绝对值 语法&#xff1a;ABS(数字)&#xff1b;返回数字的绝对值&#xff1b;若引用单元格&#xff0c;把数字换为单元格地址即可 2、INT(number)&#xff1a;向小取整 语法&#xff1a;INT(数字)&#xff1b;若引用单元格…

Element Plus el-table 数据为空时自定义内容【默认为 No Data】

1. 通过 Table 属性设置 <div class"el-plus-table"><el-table empty-text"暂无数据" :data"tableData" style"width: 100%"><el-table-column prop"date" label"Date" width"180" /&g…

Python Opencv实践 - 图像仿射变换

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) rows,cols img.shape[:2] print(img.shape[:2])#使用getAffineTransform来获得仿射变换的矩阵M #cv.getAffineTransform(…

Bingchat和ChatGPT主要区别

Bing Chat由chatgpt GPT-4技术提供支持&#xff0c;这是流行的ChatGPT的最新语言模型。Bing Chat通过更具交互性和上下文联动的响应来优化搜索引擎。它允许用户提出问题并获得更人性化、精确化或创造力的答案。用户还可以在答案末尾查看的参考来源。该工具可以充当个人研究、计…

大数据平台是什么意思?有什么用?一般包含哪些模块?

大数据时代&#xff0c;还有很多人不知道大数据平台是什么意思&#xff1f;有什么用&#xff1f;一般包含哪些模块&#xff1f;今天我们就一起来简单了解一下吧&#xff01;仅供参考哦&#xff01; 大数据平台是什么意思&#xff1f;有什么用&#xff1f;一般包含哪些模块&am…

Lnton羚通关于Optimization在【PyTorch】中的基础知识

OPTIMIZING MODEL PARAMETERS &#xff08;模型参数优化&#xff09; 现在我们有了模型和数据&#xff0c;是时候通过优化数据上的参数来训练了&#xff0c;验证和测试我们的模型。训练一个模型是一个迭代的过程&#xff0c;在每次迭代中&#xff0c;模型会对输出进行猜测&…

工程项目管理系统源码+功能清单+项目模块+spring cloud +spring boot em

​ 工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

衣服材质等整理(时常更新)

参考文章&图片来源 https://zhuanlan.zhihu.com/p/390341736 00. 天然纤维 01. 化学纤维 02. 聚酯纤维&#xff08;即&#xff0c;涤纶&#xff09; 一种由有机二元酸和二元醇通过化学缩聚制成的合成纤维。具有出色的抗皱性和保形性&#xff0c;所制衣物在穿着过程中不容…

解决git reset --soft HEAD^撤销commit时报错

今天在使用git回退功能的时候&#xff0c;遇到以下错误&#xff1a; 解决git reset --soft HEAD^撤销commit时报错 问题&#xff1a; 在进行完commit后&#xff0c;想要撤销该commit&#xff0c;于是使用了git reset --soft HEAD^命令&#xff0c;但是出现如下报错&#xff1…

android 12系统加上TTS引擎

系统层修改&#xff1a; 1.frameworks/base/packages/SettingsProvider/res/values/defaults.xml <string name"def_tts"></string> 2.frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java loadString…