SpringBoot 整合 ES (四十二)

news2025/1/15 17:35:50

我看到希望,哪怕只有微小的一束光,我也会拼尽全力去寻找

上一章简单介绍了 SpringBoot 整合 RabbitMQ (四十一), 如果没有看过,请观看上一章

ES 相应的教程,可以看老蝴蝶之前写的文章: https://blog.csdn.net/yjltx1234csdn/category_12277559.html

一. SpringBoot 整合ES

我们上一章节使用 Java API, 发现操作是很复杂的, 如果可以像操作 jpa, redis 一样, 提供对应的 JpaRestTemplate ,RedisRestTemplate 操作就好了.

其实也提供了相应的信息.

一. 一. pom.xml 引入依赖

<!--引入 spring-data-elasticsearch-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>

一.二. 配置RestHighLevelClient

一.二.一. application.yml 配置 host 和port

elasticsearch:
  host: 127.0.0.1
  port: 9200

一.二.一 配置 ES 的 Config

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.stereotype.Component;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 配置 ES
 *
 * @author yuejianli
 * @date 2022-08-18
 */
@Component
@ConfigurationProperties("elasticsearch")
@Data
public class EsConfig extends AbstractElasticsearchConfiguration {
	private String host;
	private Integer port;
	
	@Override
	public RestHighLevelClient elasticsearchClient() {
		RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port));
		return new RestHighLevelClient(restClientBuilder);
	}
}

一.三 配置相应的实体 Product

import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import lombok.Data;

/**
 * 商品
 *
 * @author yuejianli
 * @date 2022-08-18
 */
@Data
@Document(indexName = "product")
public class Product {
	@Id
	private Integer id;
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String title;
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String author;
	@Field(type = FieldType.Keyword)
	private String category;
	@Field(type = FieldType.Double)
	private Double price;
	@Field(type = FieldType.Keyword, index = false)
	private String image;
}

@Document, 指定索引名

@Id, 必须要有 id, 是全局唯一标识, 等同于 es 中的 _id

@Field 标识属性,type 指定 字段数据类型, analyzer 分词器类型, index 是否是索引, 默认为索引.

Keyword 短语, 不进行分词。

一.四 创建对应实体的 Repository

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
/**
 * 用途描述
 *
 * @author yuejianli
 * @date 2022-08-18
 */
@Repository
public interface ProductRepository extends ElasticsearchRepository<Product, Integer> {

}

是不是很像 JPA 了 ?

一.五 执行,测试整合验证

	@Test
	public void createIndexTest() {
		log.info(">>>> 创建索引成功");
	}

实体 Product, 标记了 Document 索引, 如果没有索引的话,会自动创建索引 product

如果已经存在了索引,则不会自动创建.

image-20230410133802309

二. Repository 文档操作

	@Resource
	private ProductRepository productRepository;

二.一 新增文档


/**
	 * 新增文档操作
	 */
	@Test
	public void addTest() {
		Product product = new Product();
		product.setId(1);
		product.setTitle("两个蝴蝶飞学习 ES");
		product.setCategory("图书");
		product.setPrice(40.0d);
		product.setImage("https://www.yueshushu.top");
		productRepository.save(product);
		log.info(">>> 创建生成单个文档成功");
	}

image-20230410134132484

二.二 根据 id 查询文档

	/**
	 * 根据id 查询文档
	 */
	@Test
	public void searchByIdTest() {
		Optional<Product> productOptional = productRepository.findById(1);
		if (productOptional.isPresent()) {
			Product product = productOptional.get();
			log.info(">>> 查询文档信息:{}", product);
		} else {
			log.info(">>> 没有此文档");
		}
	}
2023-04-10 13:42:03.870  INFO 41120 --- [           main] top.yueshushu.DocumentTest               : >>> 查询文档信息:Product(id=1, title=两个蝴蝶飞学习 ES, author=null, category=图书, price=40.0, image=https://www.yueshushu.top)

二.三 根据文档

	/**
	 * 更新文档
	 */
	@Test
	public void updateByIdTest() {
		// 更新文档
		Optional<Product> productOptional = productRepository.findById(1);
		if (!productOptional.isPresent()) {
			return;
		}
		Product product = productOptional.get();
		product.setPrice(38.0d);
		product.setCategory("Java");
		
		//进行更新
		productRepository.save(product);
		
		log.info(">>> 更新文档成功");
	}

image-20230410134303441

二.四 根据 id 删除文档

	/**
	 * 根据id 删除文档
	 */
	@Test
	public void deleteByIdTest() {
		productRepository.deleteById(1);
		log.info(">>> 删除文档成功");
		searchByIdTest();
	}

执行后,文档会删除。

二.五 批量添加文档

	/**
	 * 批量添加文档
	 */
	@Test
	public void batchInsertTest() {
		List<Product> list = new ArrayList<>();
		for (int i = 0; i <= 10; i++) {
			Product product = new Product();
			product.setId(i + 1);
			product.setTitle("两个蝴蝶飞学习 ES" + i);
			product.setCategory("图书");
			product.setPrice(40.0d * i);
			product.setImage("https://www.yueshushu.top");
			list.add(product);
		}
		//批量添加
		productRepository.saveAll(list);
		log.info(">>>批量添加文档成功");
	}

image-20230410134516652

二.六 全部查询文档

	/**
	 * 批量查询文档
	 */
	@Test
	public void findAllTest() {
		Iterable<Product> allList = productRepository.findAll();
		allList.forEach(
				n -> log.info("文档:{}", n)
		);
	}

image-20230410134556872

二.七 根据 id 批量查询记录

	/**
	 * 根据id 集合批量查询记录
	 */
	@Test
	public void findAllByIdListTest() {
		Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 5, 6));
		allList.forEach(
				n -> log.info("文档:{}", n)
		);
	}

image-20230410134647369

二.八 批量更新

	/**
	 * 批量更新, id一样,则更新。没有id,则添加。
	 */
	@Test
	public void batchUpdateTest() {
		Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 5, 6));
		allList.forEach(
				n -> {
					n.setPrice(10.d);
					n.setImage("http://被修改了");
				}
		);
		List<Product> list = new ArrayList<>();
		for (int i = 20; i <= 22; i++) {
			Product product = new Product();
			product.setId(i + 1);
			product.setTitle("两个蝴蝶飞学习 Java " + i);
			product.setCategory("图书");
			product.setPrice(40.0d * i);
			product.setImage("http://url1");
			list.add(product);
		}
		ArrayList<Product> findALlList = Lists.newArrayList(allList);
		list.addAll(findALlList);
		
		//批量处理
		productRepository.saveAll(list);
		
		log.info(">>>>批量修改成功");
		findAllTest();
	}

image-20230410134852002

二.九 批量删除

	/**
	 * 批量删除
	 */
	@Test
	public void batchDeleteTest() {
		Iterable<Product> allList = productRepository.findAllById(Arrays.asList(1, 2, 3));
		ArrayList<Product> findALlList = Lists.newArrayList(allList);
		productRepository.deleteAll(findALlList);
		log.info(">>>> 批量删除成功");
		findAllTest();
	}

再次查询时,会查询不到 id为 1,2,3 的记录信息

三. 查询

除了全部查询, 或者 根据id 查询, 一般会使用 ElasticsearchRestTemplate 进行查询

@Resource
	private ElasticsearchRestTemplate elasticsearchRestTemplate;

三.一 全部查询

	/**
	 * 全部查询
	 */
	@Test
	public void findAllTest() {
		NativeSearchQuery nativeSearchQuery =
				new NativeSearchQuery(QueryBuilders.matchAllQuery());
		
		SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(searchHits);
	}

	/**
	 * 展示信息
	 */
	public void showInfo(SearchHits<Product> searchResult) {
		long totalHits = searchResult.getTotalHits();
		log.info(">>> 总数:{}", totalHits);
		List<SearchHit<Product>> searchHitList = searchResult.getSearchHits();
		searchHitList.forEach(
				n -> {
					Product product = n.getContent();
					log.info(">>> 输出信息:{}", product);
					if (!CollectionUtils.isEmpty(n.getHighlightFields())){
						log.info("高亮:{}", n.getHighlightFields());
					}
				}
		);
	}

image-20230410135326131

三.二 根据id 查询

	/**
	 * 一个简单的查询
	 * id =4
	 */
	@Test
	public void simpleQueryTest() {
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
				QueryBuilders.termQuery("id", "4"));
		SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(searchHits);
	}

image-20230410135618639

三.三 分页查询

	/**
	 * 分页查询
	 * 从 0开始
	 */
	@Test
	public void pageTest() {
		NativeSearchQuery nativeSearchQuery =
				new NativeSearchQuery(QueryBuilders.matchAllQuery());
		Pageable pageable = PageRequest.of(2, 4);
		nativeSearchQuery.setPageable(pageable);
		
		// 进行查询
		SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(search);
		
	}

image-20230410135655808

三.四 分页排序查询

	/**
	 * 分页排序
	 */
	@Test
	public void sortTest() {
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(
				QueryBuilders.matchAllQuery()
		);
		Sort sort = Sort.by(Sort.Order.desc("price"));
		Pageable pageable = PageRequest.of(1, 4, sort);
		nativeSearchQuery.setPageable(pageable);
		
		SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(search);
	}

image-20230410135841426

三.五 bool 查询

	
	/**
	 * bool 查询, 类型必须是图片, id不能为5.
	 * name 可以为
	 */
	@Test
	public void boolTest() {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(QueryBuilders.termQuery("category", "图书"));
		boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", 5));
		boolQueryBuilder.should(QueryBuilders.termQuery("price", 360.0d));
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(boolQueryBuilder);
		SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(search);
	}

image-20230410135925288

三.六 range 范围查询

@Test
	public void rangeTest() {
		RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
		rangeQueryBuilder.gte(100.0);
		rangeQueryBuilder.lte(300.0d);
		
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(rangeQueryBuilder);
		
		SearchHits<Product> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(searchHits);
	}

image-20230410140034063

三.七 like 查询

	@Test
	public void likeTest() {
		FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "学哈");
		fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
		
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(fuzzyQueryBuilder);
		
		SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(search);
	}

故意将 学习 变成 学哈

image-20230410140208920

三.八 高亮展示

	@Test
	public void hightTest() {
		HighlightBuilder highlightBuilder = new HighlightBuilder();
		highlightBuilder.preTags("<font color='red'>");
		highlightBuilder.postTags("</font>");
		highlightBuilder.field("title");
		
		FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "学哈");
		fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
		NativeSearchQuery nativeSearchQuery = new NativeSearchQuery(fuzzyQueryBuilder, null, null, highlightBuilder, null);
		
		SearchHits<Product> search = elasticsearchRestTemplate.search(nativeSearchQuery, Product.class);
		showInfo(search);
		
	}
	

image-20230410140811062

三.九 组合条件查询

	@Test
	public void criteriaTest() {
		// 条件查询
		Criteria criteria = Criteria.where(new SimpleField("title")).contains("学习")
            .or( new SimpleField("id")).greaterThan("5");
		CriteriaQuery criteriaQuery = new CriteriaQuery(criteria);
		SearchHits<Product> search = elasticsearchRestTemplate.search(criteriaQuery, Product.class);
		showInfo(search);
	}

image-20230410145007327

本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/SpringBoot_ES2

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

oduct.class);
showInfo(search);

}



[外链图片转存中...(img-P5D73Are-1681367811089)]



## 三.九  组合条件查询



~~~java
	@Test
	public void criteriaTest() {
		// 条件查询
		Criteria criteria = Criteria.where(new SimpleField("title")).contains("学习")
            .or( new SimpleField("id")).greaterThan("5");
		CriteriaQuery criteriaQuery = new CriteriaQuery(criteria);
		SearchHits<Product> search = elasticsearchRestTemplate.search(criteriaQuery, Product.class);
		showInfo(search);
	}

[外链图片转存中…(img-tF7udgVf-1681367811089)]

本章节的代码放置在 github 上:

https://github.com/yuejianli/springboot/tree/develop/SpringBoot_ES2

谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

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

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

相关文章

Java 基础常识

一、Java运行机制 1.Java运行原理 编译&#xff1a;.java(源代码) ---> .class(字节码) 解释&#xff1a;.class(字节码) ---> 加载并启动JVM(类加载) ---> .class(机器指令) 执行&#xff1a;通过JVM来完成运行输出 2.Java运行过程 利用 javac 编译 .java 文件 利…

欧姆龙CP1H系列PLC通讯扩展与数据采集

一、应用场景 纺织厂的粗纱机&#xff0c;控制系统由1台欧姆龙CP1H的PLC和1台昆仑通泰MCGS的触摸屏组成&#xff0c;触摸屏连接到PLC通讯扩展的接口CP1W-CIF01&#xff08;RS232串行通讯&#xff09;。现在MES管理系统&#xff0c;需要采集设备的数据&#xff0c;要求不改变原来…

【详解C++中的引用】

文章目录 一、什么是引用二、引用规则三、引用特性四、使用场景1.做函数参数2.做返回值五、常引用 ps&#xff1a;为什么类型转换会产生临时变量&#xff1f; 六、引用和指针的区别总结 一、什么是引用 引用就是给一个变量取别名。 注意&#xff1a;这个引用不会新开辟一块空…

微信小程序自定义组件:组件间通讯

前言 略 组件间通信 组件间的基本通信方式有以下几种&#xff1a; WXML 数据绑定&#xff1a;用于父组件向子组件的指定属性设置数据&#xff0c;仅能设置 JSON 兼容数据&#xff08;自基础库版本 2.0.9 开始&#xff0c;还可以在数据中包含函数&#xff09;。具体在 组件模…

Mybatis-plus 两种分页方法(分单表和联表)

mybatis-plus分别使用 一、PageHelper插件分页使用 准备1&#xff1a;引入PageHelper依赖 <!-- pagehelper 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId>…

面试高频代码题

文章目录 链表1.删除有序链表中的重复链表2.删除有序链表的重复数组并只保留只出现过一次的结点3. 无序单链表升序排列 数组1. 冒泡排序2. 折半查找3. 快排4.给1001个数&#xff0c;有一个是重复的&#xff0c;如何不使用额外空间找出来这个数&#xff1f;&#xff08;微软&…

智能文案改写工具-智能改写工具免费

智能写作机器人 智能写作机器人&#xff0c;这是一种让人类写作变得更加简单的创新技术。它的出现&#xff0c;为内容生产领域带来了巨大的进步&#xff0c;不仅提高了人们的写作效率&#xff0c;还让优质的内容更容易被产生和共享。现在&#xff0c;让我们来了解一下智能写作…

Spring Security --- formLogin配置

目录 环境准备 配置自定义登录表单页面 配置登录成功的跳转页面方式 配置登录失败的跳转页面方式 前端表单参数获取 CustomWebSecurityConfigurerAdapter配置类代码示例 环境准备 创建springboot项目引入spring security框架引入thymeleaf模板引擎 配置自定义登录表单页面…

TryHackMe-Year of the Pig(Linux渗透测试)

Year of the Pig 有些猪会飞&#xff0c;有些有故事要讲。开始吧&#xff01; 端口扫描 循例nmap Web枚举 进入80 gobuster扫 进到/admin&#xff0c;尝试弱口令&#xff0c;给出了密码提示 密码本身的一些很简单的单词&#xff0c;密码的后三位是两位数字加一个特殊字符 我…

Flask(Jinja2)服务端模板注入漏洞(SSTI)整理

整理一下Flask框架下的SSTI漏洞相关知识&#xff1a; 漏洞原理 Flask是一个很常用的python框架&#xff0c;其中存在SSTI漏洞。 SSTI&#xff0c;服务端模板注入&#xff0c;很早就知道这个东西&#xff0c;但没有仔细整理过&#xff0c;作为一种注入漏洞&#xff0c;简单说…

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数

LeetCode算法小抄-- 最近公共祖先 和 完全二叉树的节点个数 最近公共祖先[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/)[235. 二叉搜索树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-b…

redis单机最大并发量

redis单机最大并发量 布隆过滤器多级缓存客户端缓存应用层缓存Expires和Cache-Control的区别Nginx缓存管理 服务层缓存进程内缓存进程外缓存 缓存数据一致性问题的解决引入多级缓存设计的时刻 Redis的速度非常的快,单机的Redis就可以⽀撑 每秒十几万的并发,相对于MySQL来说,性…

Linux中将Python2升到Python3

目录 1、安装依赖包 2、下载python3 方式一 方式二 3.解压文件 4.安装 5.建立软连接 1、安装依赖包 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-dev…

Mysql·分库分表

Mysql分库分表 在mysql中新建数据库用以表分库分表mycat解压后配置文件参数server.xml 主要配置mycat服务的参数&#xff0c;比如端口号&#xff0c;myact用户名和密码使用的逻辑数据库等rule.xml 主要配置路由策略&#xff0c;主要有分片的片键&#xff0c;拆分的策略&#xf…

Elasticsearch:Elasticsearch 容量规划

Elasticsearch 是一个可扩展的分布式系统&#xff0c;可为企业搜索、日志聚合、可观察性和安全性提供解决方案。 Elastic 解决方案建立在一个单一、灵活的技术堆栈之上&#xff0c;可以部署在任何地方。 要在自托管或云端运行生产环境 Elasticsearch&#xff0c;需要规划基础架…

删除注册表配置后Chrome仍然显示“由贵单位管理”解决办法

这个提示并不影响使用&#xff0c;但是强迫症看着就是难受&#xff0c;搞掉他。 现象 找到是谁触发的 浏览器输入并打开chrome://policy/ 其实看不看意义不大&#xff0c;因为你知道了也奈何不了他。 解决问题 使用百度搜索一下都是提供的删除注册表的方法&#xff08;通过…

【C++技能树】NameSpace --命名空间的使用

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

burpsuite抓包数据分析

以抓到的pikachu的数据为例&#xff1a; POST /pikachu/vul/burteforce/bf_form.php HTTP/1.1 # POST请求 被抓包的文件 http协议是1.1 Host: www.xxx.com #Host是主机 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101Firefox/49.0 #user-agent是…

【C陷阱与缺陷】两道“有趣”的代码题

如果读者不了解函数指针的&#xff0c;可以先看看这篇文章 链接 < 第一题 > 代码&#xff1a; (*(void (*)())0)();解析&#xff1a; &#x1f4ac;如果你是头一次看上面这段代码的话&#xff0c;心里一定是一个大大的问号&#xff1f;&#xff1f;&#xff1f;现在我…

C++的输入输出概述

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C &#x1f525;座右铭&#xff1a;“不要等到什么都没有了&#xff0c;才下…