SpringBoot 整合 Elasticsearch 实现全文检索

当项目里出现模糊搜索、关键词高亮、分词检索、热搜推荐、商品搜索、文章全文检索 这类需求时,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 主要两种方式:

    1. ElasticsearchRepository:简单 CRUD,类似 JPA
    1. 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)

企业级必须做数据同步,常见方案:

    1. 简单方案:新增/更新数据库时,同步更新 ES
    1. 中间件方案:Canal / Debezium 监听 binlog 自动同步
    1. 定时任务:适合数据实时性要求不高的场景

十、IK 分词器(中文必备)

  • • 安装后才能正确拆分中文

  • • 支持自定义扩展词库(如:Java、SpringBoot、云原生)

  • • 分词模式:

    • • ik_max_word:最细粒度拆分

    • • ik_smart:粗粒度拆分


十一、注意事项

    1. SpringBoot 与 ES 版本不兼容 → 启动直接报错
    1. 未安装 IK 分词 → 中文搜索效果极差
    1. keyword 不能模糊查询 → 必须用 text + 分词
    1. 高亮不生效 → 字段名与查询不匹配
    1. 深度分页性能差 → 尽量用 scroll 或 search_after
    1. 索引不存在 → 自动创建或手动创建索引

十二、总结

SpringBoot 整合 Elasticsearch 是全文检索的标准方案:

  • • 引入依赖 → 配置连接 → 定义文档 → 构建查询

  • • 简单 CRUD 用 Repository

  • • 复杂高亮、多条件、聚合用 RestTemplate


你们项目里用 ES 做什么业务?遇到过分词、同步、性能问题吗?

欢迎在评论区留言交流,关注我,持续更新 SpringBoot 从入门到企业级实战,下期我们继续讲微服务、中间件、高并发架构!


相关推荐
高频因子挖掘机7 分钟前
股票 API 返回 HTTP 429 怎么办?Python 量化系统的限流排查与重试设计
后端·github·api
mldong10 分钟前
为了 token 自由,我把 jeeflow 工作流引擎用 MoonBit 写了一遍
后端·架构
高频因子挖掘机1 小时前
从回测到实盘:量化策略为什么不应该直接依赖行情 API
后端·github·api
驭渊的小故事3 小时前
MyBatis XML 开发实战:从配置到 CRUD 全解析
xml·java·mybatis
哦虎!8 小时前
【JavaEE】网络初识
java
for_ever_love__8 小时前
MySQL ORDER BY 排序优化:从 Using filesort 到索引有序扫描(含双路 / 单路排序原理)
java·mysql·优化·存储·by·order·filesort
大鸡腿同学9 小时前
手心向上,手心向下
后端
我是人✓9 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
SelectDB技术团队9 小时前
冷热分层从建到验:Storage Policy 创建、表级与分区级绑定、SHOW TABLETS 验证的完整命令
大数据·数据库·elasticsearch·搜索引擎·数据分析·apache doris·冷热分层
欣栀♡9 小时前
JVM 频繁 Full GC 先看日志括号里的 cause,jstat 的 FGC 在 JDK 8 上会骗人
java·jvm