springBoot项目使用Elasticsearch教程
目录
- 一、引言
- (一)使用背景
- (二)版本库区别
- 二、引入依赖
- (一)springboot集成的es依赖(建议)
- (二)es提供的客户端库
- 三、配置(以yaml文件为例)
- (一)springboot集成的es依赖(建议)
- (二)es提供的客户端库
- 四、代码
- (一)springboot集成的es依赖(建议)
- 1、创建Elasticsearch实体类
- 2、创建Elasticsearch Repository
- 3、使用Elasticsearch Repository
- 4、es业务类-使用Elasticsearch模板(可选)
- 5、启动测试类
- (二)es提供的客户端库
- 1、es连接配置类-ElasticSearchConfig
- 2、es业务类-ElasticSearchService
- 3、启动测试类
- 五、总结
一、引言
(一)使用背景
Spring项目集成Elasticsearch可以带来许多好处,主要包括:
- 高性能搜索:Elasticsearch是基于Lucene的分布式搜索引擎,它能提供非常高效和低延迟的全文搜索、结构化查询以及分析。对于需要快速响应的查询操作,Elasticsearch能够提供显著的性能提升。
- 灵活的数据模型:Elasticsearch是一个文档数据库,使用JSON格式存储数据,使得数据模型非常灵活,能够处理各种结构化和半结构化数据。可以轻松应对变化的数据模型和复杂的查询需求。
- 分布式架构:Elasticsearch的分布式架构使得它具备了强大的水平扩展能力。即使数据量增长,集群也能够通过增加节点来轻松扩展,保证性能和可用性。
- 实时性:Elasticsearch支持近实时搜索,数据一旦写入便能立即查询。这对于报表服务、实时数据分析和监控等应用场景非常适用。
- Spring Data Elasticsearch支持:Spring提供了Spring Data
Elasticsearch,一个高层次的框架,用来简化Spring与Elasticsearch的集成。它封装了Elasticsearch的低层API,提供了易于使用的Repository和Template,减少了开发中的重复工作。 - 强大的聚合功能:Elasticsearch的聚合功能非常强大,可以对大量数据进行分组、统计、计算,帮助构建各种报表和分析应用。
- 易于集成和配置:Spring
Boot的自动配置功能使得Elasticsearch的集成变得非常简单。你只需要在application.properties或application.yml中配置连接信息,就能快速启用Elasticsearch的功能。 - 监控和管理工具:Elasticsearch提供了如Kibana等强大的监控和可视化工具,可以帮助开发者轻松监控和调试系统运行状态。
- 可扩展性和适应性:随着业务需求和数据量的增长,Elasticsearch能够通过集群扩展来应对。你可以随时根据需要增加更多节点、分片等。
- 简化的查询和索引操作:Spring Data
Elasticsearch提供了简单易用的API来执行索引操作、查询操作、批量操作等,开发者不需要深入掌握Elasticsearch的底层操作,能专注于业务逻辑的实现。
(二)版本库区别
1.spring-boot-starter-data-elasticsearch
功能:这是Spring Boot为集成Spring Data Elasticsearch提供的启动器。它通过Spring Data提供了简化的数据访问接口,使得开发者可以更轻松地与Elasticsearch交互。
用途:适用于Spring Boot应用,尤其是当你需要一个简化的方式来存取数据,而不想处理Elasticsearch客户端的复杂配置时。它提供了ElasticsearchRepository,自动化配置,方便进行基本的CRUD操作和查询。
优点:
自动配置:Spring Boot会自动配置好Elasticsearch连接和必要的基础设置,减少了手动配置的繁琐。
面向开发者的Repository接口:通过ElasticsearchRepository接口,开发者可以像操作普通数据库一样执行Elasticsearch的基本操作(如保存、查找、删除等)。
集成其他Spring功能:能够与Spring的事务管理、数据绑定等功能紧密集成。
简化操作:隐藏了底层的客户端实现细节,适合标准的应用开发。
2. elasticsearch-rest-high-level-client 和 elasticsearch-rest-client
功能:这两个是纯粹的Elasticsearch客户端库,分别提供了较高层次(rest-high-level-client)和较低层次(rest-client)的访问接口。它们专注于与Elasticsearch服务器之间的网络通信和数据传输,不提供Spring特有的集成。
用途:这两个依赖适合需要更精细控制或更复杂的Elasticsearch操作的场景。例如,你可以在这些客户端中直接操作Elasticsearch的REST API,进行高级的索引操作、聚合查询等,甚至实现一些自定义的网络请求和数据序列化。
优点:
高灵活性:提供了更细粒度的控制,你可以直接处理请求和响应。
支持更多功能:如果你需要对Elasticsearch进行更复杂的操作,可能会发现elasticsearch-rest-high-level-client或elasticsearch-rest-client能提供更多的灵活性和控制。
- 如果你是在SpringBoot应用中开发,且不需要过多的手动配置和细节控制,推荐使用spring-boot-starter-data-elasticsearch。
- 使用es可以用springboot集成的es库,也可以用es提供的客户端库,本文围绕两种方式展开
二、引入依赖
两种方式均可
(一)springboot集成的es依赖(建议)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${spring.boot.version}</version>
</dependency>
(二)es提供的客户端库
version具体以es的服务端版本为参考,需要匹配
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.10.2</version>
</dependency>
三、配置(以yaml文件为例)
(一)springboot集成的es依赖(建议)
spring:
data:
elasticsearch:
cluster-name: your-cluster-name
cluster-nodes: localhost:9200 # ES节点的地址和端口
username: 用户名
password: 密码
(二)es提供的客户端库
elasticsearch:
host: 服务端主机ip
port: 9200
scheme: http
username: 用户名
password: 密码
四、代码
(一)springboot集成的es依赖(建议)
1、创建Elasticsearch实体类
你需要创建一个实体类,使用@Document注解标记它为Elasticsearch文档类型,定义索引名称、类型等信息。
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "pos_order", createIndex = false)
public class PosOrder {
@Id
private String id;
private String customerName;
private double totalAmount;
// Getter and Setter methods
}
2、创建Elasticsearch Repository
Spring Data Elasticsearch提供了ElasticsearchRepository接口,用于与Elasticsearch进行交互:
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface PosOrderRepository extends ElasticsearchRepository<PosOrder, String> {
// 你可以根据需求定义其他查询方法
List<PosOrder> findByCustomerName(String customerName);
}
3、使用Elasticsearch Repository
在你的Service或Controller中注入PosOrderRepository并使用它来进行CRUD操作:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PosOrderService {
@Autowired
private PosOrderRepository posOrderRepository;
public void saveOrder(PosOrder posOrder) {
posOrderRepository.save(posOrder);
}
public List<PosOrder> findOrdersByCustomerName(String customerName) {
return posOrderRepository.findByCustomerName(customerName);
}
}
4、es业务类-使用Elasticsearch模板(可选)
如果需要执行更复杂的查询,可以使用ElasticsearchRestTemplate:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
@Service
public class PosOrderService {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
public void searchOrders() {
// 自定义查询逻辑
}
}
- 通过这些步骤,你可以在Spring Boot项目中轻松地集成Elasticsearch,实现数据的存储、查询等功能。
5、启动测试类
如果你是使用Spring Boot进行开发,确保你的服务已经注入并正常工作。你可以在Spring Boot的启动类或一个控制器中调用测试方法。
例如,在Spring Boot启动类中调用测试方法:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.beans.factory.annotation.Autowired;
@SpringBootApplication
public class ElasticsearchTestApplication implements CommandLineRunner {
@Autowired
private PosOrderService posOrderService;
public static void main(String[] args) {
SpringApplication.run(ElasticsearchTestApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// 调用测试方法
posOrderService.searchOrders(); // 或其他方法,如testIndexDocument(), testSearch(), etc.
}
}
(二)es提供的客户端库
1、es连接配置类-ElasticSearchConfig
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @className: ElasticsearchConfig
* @description: es客户端连接配置类
* @author: wuyafei
* @date: 2025/1/16 15:57
* @version: 1.0
*/
@Configuration
public class ElasticSearchConfig {
@Value("${elasticsearch.host}")
private String esHost;
@Value("${elasticsearch.port}")
private int esPort;
@Value("${elasticsearch.scheme}")
private String esScheme;
@Value("${elasticsearch.username}")
private String esUsername;
@Value("${elasticsearch.password}")
private String esPassword;
@Bean
public RestHighLevelClient client() {
// 配置基本身份验证的用户名和密码
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(esUsername, esPassword));
// 创建一个 HttpAsyncClientBuilder,并设置身份验证
HttpAsyncClientBuilder asyncClientBuilder = HttpAsyncClients.custom()
.setDefaultCredentialsProvider(credentialsProvider);
// 返回 RestHighLevelClient,并通过 setHttpClientConfigCallback 传递 HttpAsyncClientBuilder
return new RestHighLevelClient(
RestClient.builder(new HttpHost(esHost, esPort, esScheme))
.setHttpClientConfigCallback(httpClientConfig -> asyncClientBuilder)
);
}
}
注意事项:HTTP与HTTPS:如果Elasticsearch实例使用HTTPS协议,确保修改HttpHost为https,并调整端口(通常是443)
2、es业务类-ElasticSearchService
package com.hxl.bi.service.es;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;
/**
* @className: ElasticsearchService
* @description: es查询service
* @author: wuyafei
* @date: 2025/1/16 16:27
* @version: 1.0
*/
@Service
public class ElasticSearchService {
private final RestHighLevelClient client;
public ElasticSearchService(RestHighLevelClient client) {
this.client = client;
}
public void searchDocument() throws Exception {
//创建搜索请求(索引)
SearchRequest searchRequest = new SearchRequest("bi-pos-order-query-2025");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//1、全部查询
sourceBuilder.query(QueryBuilders.matchAllQuery());
// //2、精确查询
// sourceBuilder.query(QueryBuilders.termQuery("orderNo", "6660001250070030004"));
// //3、范围查询
// sourceBuilder.query(QueryBuilders.rangeQuery("orderNo").gte(6660001250070030003l).lte(6660001250070030005l));
// //4、模糊查询
// sourceBuilder.query(QueryBuilders.fuzzyQuery("orderNo", "6660001250070030004").fuzziness(Fuzziness.ONE));
// //5、多字段查询
// sourceBuilder.query(QueryBuilders.multiMatchQuery("hello", "field1", "field2"));
// //6、布尔查询-boolQuery 允许你组合多个查询,支持 must(必须匹配)、should(可以匹配)、must_not(不能匹配)等操作
// BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
// .must(QueryBuilders.termQuery("order_id", "123"))
// .should(QueryBuilders.rangeQuery("total_amount").gte(100))
// .mustNot(QueryBuilders.termQuery("status", "canceled"));
// sourceBuilder.query(boolQuery);
// searchRequest.source(sourceBuilder);
// //7、存在查询-existsQuery 用于查询某个字段是否存在。常用于检查某个字段是否被填充
// sourceBuilder.query(QueryBuilders.existsQuery("customer_name"));
// //8、前缀查询-prefixQuery 用于查询某个字段的前缀匹配。常用于搜索建议
// sourceBuilder.query(QueryBuilders.prefixQuery("orderId", "ORD"));
// //9、组合查询-constantScoreQuery 用于组合多个查询,并使用一个权重对它们进行评分。常用于提高查询结果的相关性
// sourceBuilder.query(QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("status", "active")));
// //10、聚合查询-aggregation 聚合查询用于对查询结果进行分组和统计。常用于生成报表和统计信息
// sourceBuilder.aggregation(
// AggregationBuilders.terms("agg_by_status").field("status.keyword")
// );
// //11、排序查询
// sourceBuilder.sort("total_amount", SortOrder.DESC); // 根据 `total_amount` 降序排序
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
// 打印查询到的文档总数
System.out.println("Total hits: " + response.getHits().getTotalHits().value);
// 获取并打印每个文档的详细内容
for (SearchHit hit : response.getHits()) {
// 打印文档的ID
System.out.println("Document ID: " + hit.getId());
// 打印文档的源数据 (即文档的实际内容)
System.out.println("Document Source: " + hit.getSourceAsString());
// 如果需要进一步处理每个字段,可以通过 hit.getSourceAsMap() 获取字段及其对应的值
System.out.println("Document Fields: " + hit.getSourceAsMap());
}
}
}
- 上面包含了es查询11个api,按照实际业务需要去适配
3、启动测试类
如果你是使用Spring Boot进行开发,确保你的服务已经注入并正常工作。你可以在Spring Boot的启动类或一个控制器中调用测试方法。
例如,在Spring Boot启动类中调用测试方法:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.beans.factory.annotation.Autowired;
@SpringBootApplication
public class ElasticsearchTestApplication implements CommandLineRunner {
@Autowired
private ElasticSearchService elasticsearchService;
public static void main(String[] args) {
SpringApplication.run(ElasticsearchTestApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// 调用测试方法
elasticsearchService.searchDocument(); // 或其他方法,如testIndexDocument(), testSearch(), etc.
}
}