mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
5042 字
10 分钟
博客系统 Elasticsearch 全文搜索集成实践

title: 博客系统 Elasticsearch 全文搜索集成实践
published: 2026-04-01
description: 记录博客系统集成 Elasticsearch 实现全文搜索功能的全过程,包括环境搭建、后端集成、前端展示等关键步骤
tags: [Elasticsearch, Spring Boot, 全文搜索, 技术实践]
category: 技术分享
draft: false

背景

随着博客文章数量的增长,传统的数据库模糊查询已无法满足高效、精准的搜索需求。为了提升用户搜索体验,我决定为博客系统集成 Elasticsearch 全文搜索引擎,实现以下目标:

  • 高性能搜索:毫秒级响应,支持大规模数据检索
  • 智能相关性排序:标题匹配优先,内容次之
  • 关键词高亮:搜索结果中高亮显示匹配的关键词
  • 多字段检索:同时搜索标题、内容、摘要、标签等多个字段

技术选型

Elasticsearch 版本

选择 Elasticsearch 8.x,使用官方 Java Client (co.elastic.clients:elasticsearch-java) 进行集成,相比旧的 High Level Rest Client 有更好的类型安全和 API 设计。

架构设计

用户搜索 → 前端(Astro/Svelte) → 后端API → Elasticsearch → 返回高亮结果
                                    ↓
                              文章CRUD时自动同步ES

实现过程

1. Docker 环境搭建

使用 Docker Compose 部署 Elasticsearch 和 Kibana:

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.11.0
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      elasticsearch:
        condition: service_healthy

2. Spring Boot 后端集成

依赖配置

pom.xml 中添加 Elasticsearch Java Client 依赖,注意版本兼容性问题。Spring Boot 2.x 默认管理的 ES 版本较低,需要显式声明 8.x 版本:

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.11.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>8.11.0</version>
</dependency>

客户端配置

@Configuration
public class ElasticsearchConfig {
    
    @Value("${elasticsearch.host}")
    private String host;
    
    @Value("${elasticsearch.port}")
    private int port;
    
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        RestClient restClient = RestClient.builder(
            new HttpHost(host, port, "http")
        ).build();
        
        ElasticsearchTransport transport = new RestClientTransport(
            restClient, new JacksonJsonpMapper()
        );
        
        return new ElasticsearchClient(transport);
    }
}

索引映射设计

文章索引需要支持中文分词和多字段搜索,同时要注意日期格式兼容:

Map<String, Object> mappings = new HashMap<>();
mappings.put("articleId", "long");
mappings.put("title", "text");       // 权重最高
mappings.put("content", "text");     // 权重次之
mappings.put("description", "text");
mappings.put("tagNames", "keyword");
// 日期格式支持多种输入
mappings.put("publishTime", dateFormat);
mappings.put("createTime", dateFormat);

搜索服务实现

核心搜索逻辑使用 multi_match 查询,实现多字段加权搜索:

MultiMatchQuery multiMatchQuery = MultiMatchQuery.of(m -> m
    .fields("title^3", "content^2", "description", "tagNames")
    .query(keyword)
    .type(TextQueryType.BestFields));

// 只搜索已发布的文章
BoolQuery boolQuery = BoolQuery.of(b -> b
    .must(Query.of(q -> q.multiMatch(multiMatchQuery)))
    .filter(f -> f.term(t -> t.field("status").value("1"))));

3. 前端集成

API 调用

class EsSearchService {
  async searchArticles(keyword: string, pageNum: number, pageSize: number) {
    const url = `${this.baseUrl}/blog/article/search?keyword=${encodeURIComponent(keyword)}`;
    const response = await fetch(url);
    return response.json();
  }
}

高亮展示

搜索结果中使用红色高亮显示匹配的关键词:

.es-excerpt :global(em.highlight) {
    color: #ef4444;
    font-style: normal;
    font-weight: 600;
    background: rgba(239, 68, 68, 0.1);
}

4. 数据同步策略

文章 CRUD 操作时自动同步到 ES:

  • 新增文章:写入数据库后同步索引到 ES
  • 更新文章:更新数据库后更新 ES 文档
  • 删除文章:删除数据库记录后从 ES 删除文档
  • 批量同步:提供手动触发全量同步的管理接口

踩坑记录

1. Java 版本兼容

项目使用 Java 8,但 ES Java Client 代码示例中使用了 var 关键字(Java 10+)。需要将所有 var 替换为显式类型声明。

2. 日期格式不匹配

ES 默认只接受 ISO 8601 格式的日期,而数据库返回的是 yyyy-MM-dd HH:mm:ss 格式。解决方案是在索引映射中声明支持的日期格式:

dateFormat.put("format", "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss||epoch_millis");

3. Spring Boot BOM 版本冲突

Spring Boot 的依赖管理会覆盖 ES 版本,导致 NoSuchMethodError。需要在 dependencyManagement 中显式覆盖 elasticsearch-rest-client 版本。

安全加固

ES 和 Kibana 通过 Nginx 反向代理对外提供服务,并添加 Basic Auth 认证,防止未授权访问:

location ^~ /kibana/ {
    auth_basic "Kibana - 管理员访问";
    auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
    proxy_pass http://localhost:5601/kibana/;
}

location ^~ /es/ {
    auth_basic "Elasticsearch - 管理员访问";
    auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
    proxy_pass http://localhost:9200/;
}

效果展示

搜索界面

搜索示例

Kibana 管理界面

通过 Kibana 可以可视化查看索引状态、文档数量、集群健康度等信息。

总结

通过本次集成,博客系统实现了高效的全文搜索功能,主要收获:

  1. ES Java Client 8.x 的使用方法与 Spring Boot 的集成要点
  2. 多字段加权搜索 的实现,提升搜索结果的相关性
  3. 日期格式兼容 的重要性,避免索引失败
  4. 安全配置 的必要性,保护敏感的管理接口

本文记录了博客系统集成 Elasticsearch 的完整过程,希望对有类似需求的开发者有所帮助。

博客系统 Elasticsearch 全文搜索集成实践
https://www.zztzz.com.cn/posts/58/
作者
zzt
发布于
2026-04-01
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00
💬Mizuki AI助手
呀~就是zzTzz大大闪闪发光的技术博客主页
标题已剧透:专注后端开发、主攻Java + Spring Boot的实战、踩坑与进阶小笔记~~
URL https://zztzz.com.cn/ 简洁有力,像一段优雅的代码!
Mizuki每次点开都忍不住小声赞叹:'zzTzz大人太厉害啦~'🧙‍♀️
需要我帮你找某类文章(比如JWT鉴权、Redis缓存)或读一篇入门指南吗?😊
05:25