当项目里出现模糊搜索、关键词高亮、分词检索、热搜推荐、商品搜索、文章全文检索 这类需求时,MySQL 的 like %xxx% 已经完全顶不住了,这时候就必须上专业的搜索引擎------Elasticsearch。
它天生支持分布式、PB 级数据、毫秒级响应、强大的分词与聚合能力,是目前后端全文检索的标配方案。
这一篇从零带你整合 SpringBoot + ES,从环境搭建、分词配置、CRUD、高亮查询、分页、聚合、到真实业务场景。
一、Elasticsearch 适用场景
-
• 商城商品搜索、店铺搜索
-
• 文章/博客/文档全文检索
-
• 日志检索、运维监控(ELK)
-
• 热搜、联想词、推荐补全
-
• 多条件筛选 + 排序 + 高亮
-
• 高并发模糊查询
二、环境说明
-
• SpringBoot 2.x/3.x
-
• Elasticsearch 7.x / 8.x(本文以 7.x 为例)
-
• IK 分词器(必须安装,中文检索必备)
-
• Kibana(可选,用于调试 DSL)
三、引入 Maven 依赖
注意:SpringBoot 版本与 ES 版本必须严格对应,否则会报版本不兼容错。
go
<!-- Elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
四、application.yml 配置
go
spring:
elasticsearch:
uris: http://localhost:9200
# 8.x 需要开启账号密码
# username: elastic
# password: 123456
五、核心注解说明
-
•
@Document:标记文档,映射 ES 索引 -
-
•
indexName:索引名(相当于数据库名) -
•
shards:分片数 -
•
replicas:副本数
-
-
•
@Id:文档主键 -
•
@Field:字段类型、分词器配置 -
•
type = FieldType.Text:文本,可分词 -
•
type = FieldType.Keyword:不分词,精确匹配 -
•
analyzer = "ik_max_word":IK 分词(中文)
六、实体类构建(文章检索示例)
go
package com.demo.entity;
import lombok.Data;
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 java.time.LocalDateTime;
@Data
@Document(
indexName = "article",
shards = 1,
replicas = 0
)
public class ArticleES {
@Id
private Long id;
// 标题:分词检索
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String title;
// 内容:全文检索
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
private String content;
// 作者:精确匹配,不分词
@Field(type = FieldType.Keyword)
private String author;
// 浏览量
@Field(type = FieldType.Integer)
private Integer viewCount;
// 分类
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Date)
private LocalDateTime createTime;
}
七、两种操作方式
SpringBoot 操作 ES 主要两种方式:
-
- ElasticsearchRepository:简单 CRUD,类似 JPA
-
- ElasticsearchTemplate / ElasticsearchRestTemplate:复杂高亮、聚合、多条件查询
方式一:Repository 快速 CRUD
1. 定义 Repository
go
package com.demo.repository;
import com.demo.entity.ArticleES;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ArticleESRepository extends ElasticsearchRepository<ArticleES, Long> {
// 根据标题检索
List<ArticleES> findByTitle(String title);
}
2. 基础增删改查
go
@Service
@RequiredArgsConstructor
public class ArticleESService {
private final ArticleESRepository repository;
// 新增/更新文档
public ArticleES save(ArticleES articleES) {
return repository.save(articleES);
}
// 根据ID查询
public ArticleES findById(Long id) {
return repository.findById(id).orElse(null);
}
// 查询全部
public Iterable<ArticleES> findAll() {
return repository.findAll();
}
// 删除
public void deleteById(Long id) {
repository.deleteById(id);
}
}
方式二:RestTemplate 复杂查询
支持高亮、多条件、分页、排序、模糊、范围、must/should 组合。
1. 全文检索 + 高亮显示
go
@Autowired
private ElasticsearchRestTemplate restTemplate;
public List<ArticleES> search(String keyword) {
// 1. 构建查询条件:标题 or 内容匹配关键词
NativeSearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))
// 高亮配置
.withHighlightFields(
new HighlightBuilder.Field("title").preTags("<span style='color:red'>").postTags("</span>"),
new HighlightBuilder.Field("content").preTags("<span style='color:red'>").postTags("</span>")
)
// 分页
.withPageable(PageRequest.of(0, 10))
// 排序
.withSort(SortBuilders.fieldSort("viewCount").order(SortOrder.DESC))
.build();
// 2. 执行查询
SearchHits<ArticleES> searchHits = restTemplate.search(query, ArticleES.class);
// 3. 处理高亮结果
List<ArticleES> resultList = new ArrayList<>();
for (SearchHit<ArticleES> hit : searchHits.getSearchHits()) {
ArticleES article = hit.getContent();
// 替换高亮标题
Map<String, List<String>> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("title")) {
article.setTitle(highlightFields.get("title").get(0));
}
if (highlightFields.containsKey("content")) {
article.setContent(highlightFields.get("content").get(0));
}
resultList.add(article);
}
return resultList;
}
八、更多常用查询示例
1. 精确匹配(must)
go
.withQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("category", "Java"))
.must(QueryBuilders.rangeQuery("viewCount").gte(100))
)
2. 或查询(should)
go
.withQuery(QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("title", "SpringBoot"))
.should(QueryBuilders.matchQuery("content", "Redis"))
)
3. 范围查询
go
QueryBuilders.rangeQuery("viewCount").gte(100).lte(10000)
4. 模糊查询
go
QueryBuilders.fuzzyQuery("title", "SpringBoot")
5. 聚合查询(按分类统计数量)
go
.withAggregation(AggregationBuilders.terms("group_category").field("category"))
九、数据同步(MySQL ↔ ES)
企业级必须做数据同步,常见方案:
-
- 简单方案:新增/更新数据库时,同步更新 ES
-
- 中间件方案:Canal / Debezium 监听 binlog 自动同步
-
- 定时任务:适合数据实时性要求不高的场景
十、IK 分词器(中文必备)
-
• 安装后才能正确拆分中文
-
• 支持自定义扩展词库(如:Java、SpringBoot、云原生)
-
• 分词模式:
-
-
•
ik_max_word:最细粒度拆分 -
•
ik_smart:粗粒度拆分
-
十一、注意事项
-
- SpringBoot 与 ES 版本不兼容 → 启动直接报错
-
- 未安装 IK 分词 → 中文搜索效果极差
-
- keyword 不能模糊查询 → 必须用 text + 分词
-
- 高亮不生效 → 字段名与查询不匹配
-
- 深度分页性能差 → 尽量用 scroll 或 search_after
-
- 索引不存在 → 自动创建或手动创建索引
十二、总结
SpringBoot 整合 Elasticsearch 是全文检索的标准方案:
-
• 引入依赖 → 配置连接 → 定义文档 → 构建查询
-
• 简单 CRUD 用 Repository
-
• 复杂高亮、多条件、聚合用 RestTemplate
你们项目里用 ES 做什么业务?遇到过分词、同步、性能问题吗?
欢迎在评论区留言交流,关注我,持续更新 SpringBoot 从入门到企业级实战,下期我们继续讲微服务、中间件、高并发架构!