SpringBoot接入Elasticsearch完整教程
作者:奋力向前123
文章浏览阅读306次,点赞7次,收藏3次。SpringBoot 接入 Elasticsearch 完整教程
版本说明:
- SpringBoot 2.7.x → Spring Data ES 4.4.x → ES 7.17.x,客户端:
RestHighLevelClient(已废弃) - SpringBoot 3.x → Spring Data ES 5.x → ES 8.x,客户端:新官方 Java API Client(推荐)
- 三种开发方式:
ElasticsearchRepository:简单 CRUD,类似 Mybatis-Repository,适合简单业务ElasticsearchOperations(新版替代 ElasticsearchRestTemplate):复杂 DSL、分页、高亮、聚合,企业最常用- 原生
ElasticsearchClient:完全原生官方客户端,自由度最高
一、前置准备
- 部署 Elasticsearch(单机 / 集群),ES 8 默认开启 HTTPS + 账号认证,开发可临时关闭安全
- 中文检索建议安装 IK 分词器(版本必须和 ES 完全一致)
- 确保 SpringBoot、Spring Data ES、ES 服务端 版本兼容(版本不匹配是最常见报错)
二、Maven 依赖(SpringBoot3 + ES8 推荐)
<!-- Spring Data Elasticsearch 自动引入新版Java API Client -->
<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>SpringBoot2.7 + ES7 旧项目:同样使用 starter,底层自动使用 RestHighLevelClient(不再推荐新项目使用)
三、application.yml 配置
spring:
elasticsearch:
uris: http://127.0.0.1:9200 #集群多个节点逗号分隔
# ES开启认证时配置账号密码
# username: elastic
# password: elastic
connection-timeout: 10s
socket-timeout: 30s
# 调试:打印ES请求DSL
logging:
level:
org.springframework.data.elasticsearch: DEBUG四、定义 ES 实体(Document 映射索引)
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
// indexName:索引名(小写,不能大写)createIndex=true项目启动自动创建索引
@Document(indexName = "product", createIndex = true)
public class ProductDoc {
// @Id 对应ES文档 _id
@Id
private Long id;
// Text:分词,全文检索;ik_max_word 细粒度分词,ik_smart粗粒度
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String name;
// Keyword:不分词,精确匹配、筛选、聚合
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Double)
private Double price;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String desc;
}注解说明:
@Document:标记实体为 ES 文档@Id:文档唯一 IDFieldType.Text:分词检索;FieldType.Keyword:精确匹配
方式 1:ElasticsearchRepository(简单 CRUD)
1. 创建 Repository 接口
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
// 泛型:实体类,主键类型
public interface ProductRepository extends ElasticsearchRepository<ProductDoc, Long> {
// 【方法名自动推导查询】根据名称分词查询
List<ProductDoc> findByName(String name);
// 自定义DSL语句查询
// @Query("{\"match\": {\"name\": \"?0\"}}")
// List<ProductDoc> searchName(String keyword);
}2. 使用示例
@Service
@RequiredArgsConstructor
public class ProductService {
private final ProductRepository productRepository;
// 新增/全量更新(id存在则覆盖,不存在新增)
public void save(ProductDoc doc) {
productRepository.save(doc);
}
// 根据id查询
public Optional<ProductDoc> findById(Long id) {
return productRepository.findById(id);
}
// 删除
public void delete(Long id) {
productRepository.deleteById(id);
}
// 分页
public Page<ProductDoc> page(String keyword, int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return productRepository.findByName(keyword, pageable);
}
}✅ 优点:代码极简;❌ 缺点:复杂 bool 组合、高亮、聚合不好实现
方式 2:ElasticsearchOperations(推荐,复杂查询)
Spring Data ES5.x 推荐注入 ElasticsearchOperations(替代旧版 ElasticsearchRestTemplate),支持构建原生 DSL、分页、排序、高亮、聚合Spring
@Service
@RequiredArgsConstructor
public class ProductEsService {
private final ElasticsearchOperations esOperations;
// 1. 新增文档
public ProductDoc saveDoc(ProductDoc doc) {
return esOperations.save(doc);
}
// 2. 根据id查询
public ProductDoc getById(Long id) {
return esOperations.get(String.valueOf(id), ProductDoc.class);
}
// 3. 删除文档
public void deleteDoc(Long id) {
esOperations.delete(String.valueOf(id), ProductDoc.class);
}
// 4. 复杂组合查询:关键词检索 + 分类筛选 + 价格区间 + 分页 + 高亮
public SearchHits<ProductDoc> search(String keyword, String category, Double minPrice, int pageNum, int pageSize) {
// 构建Bool查询
BoolQuery boolQuery = BoolQuery.builder()
// must:必须匹配(分词检索商品名)
.must(m -> m.match(ma -> ma.field("name").query(keyword)))
// filter:过滤,不计算相关度
.filter(f -> f.term(t -> t.field("category").value(category)))
.filter(f -> f.range(r -> r.field("price").gte(JsonData.of(minPrice))))
.build();
// 高亮配置
HighlightOptions highlight = HighlightOptions.builder()
.field("name", h -> h.preTags("<em>").postTags("</em>"))
.build();
NativeSearchQuery searchQuery = NativeSearchQueryBuilder()
.withQuery(boolQuery)
.withHighlightOptions(highlight)
.withPageable(PageRequest.of(pageNum, pageSize)) // page从0开始
.withSort(Sort.by(Sort.Direction.DESC, "price"))
.build();
// 执行查询
return esOperations.search(searchQuery, ProductDoc.class);
}
}方式 3:原生 ElasticsearchClient(官方底层客户端,极致灵活)
适合聚合、向量检索、ES 新特性,完全对齐官方 DSL,强类型编译校验CSDN博...
@Service
@RequiredArgsConstructor
public class ProductNativeService {
private final ElasticsearchClient esClient;
// 新增文档
public void insert(ProductDoc doc) throws IOException {
esClient.index(i -> i
.index("product")
.id(doc.getId().toString())
.document(doc)
);
}
// match分词查询
public SearchResponse<ProductDoc> search(String keyword) throws IOException {
return esClient.search(s -> s
.index("product")
.query(q -> q.match(m -> m.field("name").query(keyword))),
ProductDoc.class
);
}
}五、常用高级操作
1. 索引管理(创建 / 删除索引)
// 注入 ElasticsearchOperations
IndexOperations indexOps = esOperations.indexOps(ProductDoc.class);
// 判断索引是否存在
boolean exist = indexOps.exists();
// 删除索引
if(exist){
indexOps.delete();
}
// 创建索引+自动映射mapping
indexOps.create();
indexOps.putMapping();2. 批量导入(Bulk 批量插入,大数据必用)
List<ProductDoc> list = new ArrayList<>(); // 封装多条数据 esOperations.save(list);
3. 高亮结果解析
search 返回 SearchHits<ProductDoc>,遍历 SearchHit 获取 getHighlightFields() 替换原始文本
六、常见踩坑总结
- 版本不匹配:90% 报错来源,严格对齐 SpringBoot → Spring Data ES → ES 服务端版本
- 索引名不能大写,ES 底层全小写
- Text 字段用于分词搜索,Keyword 用于筛选、分组、精确匹配,不要混用
- ES8 默认开启 SSL 和账号认证,开发环境关闭安全,生产务必开启
- 深分页(from+size 超过 10000)会报错,需使用
scroll滚动分页 /search_after - 数据库和 ES 数据一致性:通过 MQ 双写、binlog 同步(Canal)保证最终一致性,不要依赖事务
- IK 分词器版本必须和 ES 版本一致,否则 ES 启动失败
以上就是SpringBoot接入Elasticsearch完整教程的详细内容,更多关于SpringBoot接入Elasticsearch的资料请关注脚本之家其它相关文章!
