[Java实战]Spring Boot整合Elasticsearch(二十六)
摘要:本文通过完整的实战演示,详细讲解如何在Spring Boot项目中整合Elasticsearch,实现数据的存储、检索和复杂查询功能。包含版本适配方案、Spring Data Elasticsearch高级特性以及性能优化建议。
一、Elasticsearch核心概念与优势
1.1 为什么要选择Elasticsearch?
- 近实时搜索:数据变更后1秒内即可被检索
- 分布式架构:天然支持水平扩展,轻松应对海量数据
- 全文检索能力:基于倒排索引,支持模糊查询、同义词、分词等
- 多数据类型:支持结构化、非结构化和地理空间数据
1.2 核心概念解析
概念 | 类比关系型数据库 | 说明 |
---|---|---|
Index | Database | 数据容器,包含多个文档类型 |
Type | Table | 7.x版本后已废弃 |
Document | Row | 数据的基本单元 |
Field | Column | 文档的字段 |
Shard | 分区 | 索引的横向拆分单元 |
二、环境准备与版本适配
2.1 组件版本选择
- Spring Boot 2.7.x
- Elasticsearch 7.10.x
- Spring Data Elasticsearch 4.4.x
<!-- pom.xml 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.2 配置Elasticsearch连接
# application.yml
spring:
elasticsearch:
uris: http://localhost:9200
username: elastic
password: your_password
三、实现数据存储与检索
3.1 定义领域模型
@Document(indexName = "articles")
public class Article {
@Id
private String id;
@Field(type = FieldType.Text)
private String title;
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
private LocalDateTime createTime;
}
3.2 创建Repository接口
public interface ArticleRepository extends ElasticsearchRepository<Article, String> {
// 自定义查询方法
List<Article> findByTitleContaining(String keyword);
@Query("{\"match\": {\"title\": {\"query\": \"?0\"}}}")
Page<Article> searchByTitle(String keyword, Pageable pageable);
}
3.3 基础CRUD操作示例
@Service
@RequiredArgsConstructor
public class ArticleService {
@Autowired
private ArticleRepository repository;
public void save(Article article) {
repository.save(article);
}
public Page<Article> search(String keyword, int page, int size) {
return (Page<Article>) repository.searchByTitle(keyword,
PageRequest.of(page, size, Sort.by("createTime").descending()));
}
3.4 controller编写
@RestController
@RequestMapping("/art")
public class ArticleController {
@Autowired
private ArticleService articleService;
//保存数据
@PostMapping("/saveArt")
public void saveArtInfo(@RequestBody Article art){
Article article = new Article();
article.setTitle("Spring Boot整合Elasticsearch实战");
article.setCategory("技术文章");
article.setCreateTime(LocalDateTime.now());
System.out.println("=======保存数据======");
articleService.save(article);
// 查询所有文档
//articleService.findAllArticles();
}
}
3.5 接口测试
#post请求
http://localhost:8080/art/saveArt
ES中查看数据:
curl -X GET "localhost:9200/articles/_search?pretty"
四、高级查询实战
4.1 组合查询(Bool Query)
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("title", "Spring"))
.filter(QueryBuilders.rangeQuery("createTime").gte("now-7d/d"));
queryBuilder.withQuery(boolQuery);
SearchHits<Article> hits = elasticsearchOperations.search(queryBuilder.build(), Article.class);
4.2 聚合分析示例
TermsAggregationBuilder categoryAgg = AggregationBuilders.terms("category_count")
.field("category.keyword")
.size(10);
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.addAggregation(categoryAgg)
.build();
SearchHits<Article> searchHits = elasticsearchOperations.search(searchQuery, Article.class);
Terms terms = searchHits.getAggregations().get("category_count");
五、性能优化建议
索引策略优化
- 合理设置分片数(建议每个分片大小在10-50GB)
- 使用别名实现零停机索引切换
查询优化技巧
- 避免深度分页(推荐使用search_after)
- 使用filter上下文缓存高频过滤条件
硬件配置推荐
- SSD硬盘优先
- JVM堆内存不超过32GB
- 预留50%内存给文件系统缓存
六、常见问题排查
Q1:出现NoNodeAvailableException异常
- 检查ES集群状态:
GET _cluster/health
- 验证网络连接和防火墙设置
Q2:查询结果不符合预期
- 使用Analyze API验证分词效果:
POST _analyze { "analyzer": "ik_max_word", "text": "分布式搜索引擎" }
参考文献:
如果你在使用过程中遇到任何问题,欢迎在评论区留言交流。感谢你的阅读,希望这篇文章对你有所帮助!