Spring Boot 整合 Elasticsearch 及实战应用
这次内容详细介绍如何使用 Spring Boot 整合 Elasticsearch,并提供几个实际应用案例。内容涵盖 Elasticsearch 的基本概念、Spring Boot 整合步骤、实战应用示例以及优化建议。
1、Elasticsearch 概念及作用
Elasticsearch 是一个基于 Apache Lucene 构建的分布式、RESTful 风格的搜索和数据分析引擎。它专门为处理大规模数据而设计,提供近实时的搜索能力,支持结构化、全文、地理空间等多种类型的查询。
核心特性与作用包括:
- 分布式架构:支持水平扩展,通过分片(Shard)和副本(Replica)机制实现高可用与负载均衡。
- 近实时搜索:数据索引后几乎立即可搜,适用于需要快速响应的场景。
- 强大的全文搜索:基于倒排索引,支持复杂的查询、高亮显示、模糊匹配等。
- 数据分析与聚合:提供丰富的聚合功能(Aggregations),用于对数据进行统计和分析。
- 多类型数据支持:除了文本,还能处理日志、指标、地理空间数据等。
- 易用性与扩展性:提供 RESTful API,支持多种编程语言集成,并拥有活跃的生态系统。
Elasticsearch 广泛应用于电商搜索、日志分析、实时监控、数据可视化等领域。
2、Spring Boot 整合 Elasticsearch
2.1、环境准备与依赖配置
在 Spring Boot 项目中,首先需要在 pom.xml 中添加 Elasticsearch 相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
在 application.properties 中配置 Elasticsearch 连接信息:
spring.elasticsearch.rest.uris=http://localhost:9200
spring.data.elasticsearch.repositories.enabled=true
如果连接 Elasticsearch 集群,可以配置集群名称和节点:
spring.data.elasticsearch.cluster-name=your-cluster-name
spring.data.elasticsearch.cluster-nodes=ip1:port1,ip2:port2
2.2、创建 Elasticsearch 实体类
使用 @Document 注解定义一个实体类,映射到 Elasticsearch 的索引:
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
@Document(indexName = "articles")
public class Article {
@Id
private String id;
private String title;
private String content;
// 无参构造器、有参构造器、getter和setter方法
public Article() {}
public Article(String id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
// Getter 和 Setter 方法
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; }
}
2.3、创建 Elasticsearch Repository
创建一个继承 ElasticsearchRepository 的接口,用于数据操作:
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface ArticleRepository extends ElasticsearchRepository<Article, String> {
// 根据内容进行全文搜索
List<Article> findByContentContaining(String content);
// 根据标题搜索
List<Article> findByTitleContaining(String title);
}
2.4、控制器层实现
创建一个 REST 控制器来处理搜索请求:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/articles")
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
// 搜索文章
@GetMapping("/search")
public List<Article> searchArticles(@RequestParam String query) {
return articleRepository.findByContentContaining(query);
}
// 添加新文章
@PostMapping
public Article createArticle(@RequestBody Article article) {
return articleRepository.save(article);
}
}
3、Elasticsearch 实战应用案例
3.1、案例一:电商平台商品搜索与高亮显示
业务场景:电商平台需要为用户提供高效的商品搜索功能,在海量数据中快速返回匹配结果,并高亮显示关键字。
实现步骤:
- 创建商品索引: 使用 Elasticsearch 的 REST API 创建商品索引:
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text" },
"description": { "type": "text" },
"price": { "type": "float" }
}
}
}
- 添加商品数据:
POST /products/_doc/1
{
"name": "华为 Mate 70",
"description": "Mate 70 手机是搭载纯血鸿蒙NEXT 系统的第一款旗舰机",
"price": 6500
}
- 实现搜索与高亮: 在 Repository 中定义复杂查询方法:
import org.springframework.data.elasticsearch.annotations.Query;
import java.util.List;
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
@Query("{\"multi_match\": {\"query\": \"?0\", \"fields\": [\"name\", \"description\"]}}")
List<Product> findByQuery(String query);
}
使用 Elasticsearch 的高亮查询:
@Service
public class ProductService {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
public List<SearchHit<Product>> searchProductsWithHighlight(String keyword) {
// 创建查询条件
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery(keyword, "name", "description"))
.withHighlightFields(
new HighlightBuilder.Field("name").preTags("<em>").postTags("</em>"),
new HighlightBuilder.Field("description").preTags("<em>").postTags("</em>")
)
.build();
SearchHits<Product> searchHits = elasticsearchTemplate.search(searchQuery, Product.class);
return searchHits.getSearchHits();
}
}
3.2、案例二:日志收集与分析系统
业务场景:对分布式系统中的应用日志进行集中管理、实时监控与分析,快速定位系统错误和性能瓶颈。
解决方案:
- 使用ELK/EFK 技术栈:
- Filebeat/Logstash:收集应用日志
- Elasticsearch:存储和索引日志数据
- Kibana:日志可视化和监控
- 创建日志索引:
- 实现日志分析:
public interface LogRepository extends ElasticsearchRepository<AppLog, String> {
// 统计各日志级别的数量
@Query("{\"aggs\": {\"levels\": {\"terms\": {\"field\": \"level.keyword\"}}}}")
AggregatedPage<AppLog> countByLevel();
// 根据时间范围查询日志
List<AppLog> findByTimestampBetween(String startTime, String endTime);
}
3.3、案例三:复杂查询与聚合分析
业务场景:新闻分析平台需要对大量文章进行复杂查询和内容分析,例如统计特定关键词的出现频率。
实现方案:
- 布尔查询: 组合多个查询条件:
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.BoolQueryBuilder;
public List<Article> complexSearch(String mustTerm, String shouldTerm, String mustNotTerm) {
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("title", mustTerm))
.should(QueryBuilders.matchQuery("content", shouldTerm))
.mustNot(QueryBuilders.matchQuery("status", mustNotTerm));
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQuery)
.build();
return elasticsearchTemplate.search(searchQuery, Article.class).getContent();
}
- 聚合分析: 统计标签出现频率:
public void tagAggregation() {
TermsAggregationBuilder aggregation = AggregationBuilders
.terms("tags_aggregation")
.field("tags.keyword");
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.addAggregation(aggregation)
.build();
SearchHits<Article> searchHits = elasticsearchTemplate.search(searchQuery, Article.class);
Terms terms = searchHits.getAggregations().get("tags_aggregation");
for (Terms.Bucket bucket : terms.getBuckets()) {
System.out.println("标签: " + bucket.getKey() + ", 数量: " + bucket.getDocCount());
}
}
4、性能优化建议
- 索引优化:
- 为常用字段建立合适的索引映射
- 根据数据类型选择合适的分析器
- 查询优化:
- 使用过滤器缓存结果
- 限制检索范围,避免全索引扫描
- 使用分页减少返回数据量
- 集群与分片配置:
- 根据数据量和硬件配置合理设置分片数量和副本
- 监控节点负载,避免热点数据问题
- 批量操作: 对于大量数据插入和更新,使用批量操作提高效率:
@Service
public class BulkOperationService {
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
public void bulkInsert(List<Article> articles) {
List<IndexQuery> queries = articles.stream()
.map(article -> new IndexQueryBuilder()
.withId(article.getId())
.withObject(article)
.build())
.collect(Collectors.toList());
elasticsearchTemplate.bulkIndex(queries, BulkOptions.defaultOptions());
}
}
5、总结
主要介绍了 Spring Boot 与 Elasticsearch 的整合方法,并通过电商搜索、日志分析和复杂查询三个实际案例展示了 Elasticsearch 的应用价值。通过合理的配置和优化,Elasticsearch 能够为应用程序提供强大的搜索和数据分析能力,满足大数据量下的高性能需求。
Elasticsearch 的分布式特性和丰富的功能集使其成为现代应用中不可或缺的搜索和分析引擎,合理利用其特性可以显著提升应用的搜索体验和数据处理能力。

谢谢你看我的文章,既然看到这里了,如果觉得不错,随手点个赞、转发、在看三连吧,感谢感谢。那我们,下次再见。
您的一键三连,是我更新的最大动力,谢谢
山水有相逢,来日皆可期,谢谢阅读,我们再会
我手中的金箍棒,上能通天,下能探海
- 点赞
- 收藏
- 关注作者
评论(0)