Spring Boot 整合 Easy-ES 实战操作详解
Easy-ES 是一个基于 Elasticsearch 的 ORM 框架,类似于 MyBatis-Plus,但专注于简化 ES 操作。它提供了 MySQL-like 的语法,支持 Lambda 风格查询、自动映射、分页、聚合等功能,极大降低了直接使用 RestHighLevelClient 的复杂度。Easy-ES 适合需要全文搜索、复杂查询的 Spring Boot 项目,如电商搜索、日志分析等。
本教程基于 Easy-ES 最新版本(假设 2.x,实际以 GitHub 最新为准),从零搭建一个简单书籍管理系统,演示 CRUD 操作。假设你有基本的 Spring Boot 和 Elasticsearch 知识。
前提条件
- JDK 8+(推荐 17+)
- Spring Boot 2.7+ 或 3.x
- Elasticsearch 7.x 或 8.x(本地或云端安装,启动后访问 http://localhost:9200 确认运行)
- Maven 或 Gradle 作为构建工具
- IDE 如 IntelliJ IDEA
步骤 1: 创建 Spring Boot 项目
使用 Spring Initializr 创建项目:
- Group: com.example
- Artifact: easy-es-demo
- Dependencies: Spring Web, Spring Boot DevTools(后续添加 Easy-ES)
下载后导入 IDE。
步骤 2: 添加 Easy-ES 依赖
在 pom.xml 中添加 Easy-ES Boot Starter 依赖(从官方 GitHub 获取最新版本):
<dependencies>
<!-- Easy-ES Boot Starter -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>easy-es-boot-starter</artifactId>
<version>2.7.1</version> <!-- 替换为最新版本,从 Maven Central 或 GitHub 检查 -->
</dependency>
<!-- Lombok 可选,简化实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
更新 Maven 依赖。
步骤 3: 配置 Elasticsearch 连接
在 application.yml 或 application.properties 中配置 ES 连接。Easy-ES 会自动配置,无需额外 Bean。
# application.yml
easy-es:
address: 127.0.0.1:9200 # ES 地址,多个用逗号分隔
username: elastic # 如果有认证
password: your_password
schema: http # 或 https
connect-timeout: 1000 # 连接超时(ms)
socket-timeout: 30000 # 套接字超时(ms)
request-timeout: 30000 # 请求超时(ms)
connect-request-timeout: 1000
# 其他可选配置:enable-content-log: false(关闭内容日志)、enable-global-select: true 等
# Spring Boot 日志级别(可选,调试用)
logging:
level:
org.dromara.easyes: debug
最佳实践:
- 生产环境使用 HTTPS 和认证。
- 如果 ES 集群,配置多个 address。
- 监控日志级别,调试时设为 debug,便于查看生成的 ES DSL 查询。
步骤 4: 创建实体类(Document)
实体类对应 ES 中的文档。使用 @EsId 标记 ID,使用 @EsIndexName 指定索引名(可选)。
import lombok.Data;
import org.dromara.easyes.annotation.IndexField;
import org.dromara.easyes.annotation.IndexId;
import org.dromara.easyes.annotation.IndexName;
import org.dromara.easyes.common.constants.EsConstants;
import org.dromara.easyes.common.enums.IdType;
@Data
@IndexName("book_index") // 指定 ES 索引名
public class Book {
@IndexId(type = IdType.CUSTOMIZE) // ID 类型,自定义或 PRIMARY_KEY
private String id; // ES 文档 ID
@IndexField(fieldType = EsConstants.TEXT) // 指定字段类型
private String title; // 书名
@IndexField(fieldType = EsConstants.KEYWORD)
private String author; // 作者
@IndexField(fieldType = EsConstants.DOUBLE)
private Double price; // 价格
@IndexField(fieldType = EsConstants.DATE)
private String publishDate; // 出版日期 (格式: yyyy-MM-dd)
}
最佳实践:
- 使用
@IndexField指定类型,避免默认映射错误(e.g., text 用于全文搜索,keyword 用于精确匹配)。 - ID 类型:CUSTOMIZE 为自定义字符串 ID,PRIMARY_KEY 为自增。
- 如果索引不存在,Easy-ES 会自动创建。
步骤 5: 创建 Mapper 接口
Mapper 继承 BaseEsMapper<T>,无需实现方法,即可使用 CRUD。
import org.dromara.easyes.core.base.BaseEsMapper;
public interface BookMapper extends BaseEsMapper<Book> {
// 可自定义方法,但基础 CRUD 已内置
}
最佳实践:
- 继承后即可调用
insert、selectById、updateById、deleteById等。 - 对于复杂查询,使用 LambdaEsQueryWrapper 构建。
步骤 6: 创建 Service 层
Service 使用 Mapper 进行业务操作。
import lombok.RequiredArgsConstructor;
import org.dromara.easyes.core.conditions.LambdaEsQueryWrapper;
import org.dromara.easyes.core.conditions.LambdaEsUpdateWrapper;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class BookService {
private final BookMapper bookMapper;
// 新增书籍
public void addBook(Book book) {
bookMapper.insert(book);
}
// 查询所有书籍
public List<Book> getAllBooks() {
LambdaEsQueryWrapper<Book> wrapper = new LambdaEsQueryWrapper<>();
return bookMapper.selectList(wrapper);
}
// 根据标题模糊搜索
public List<Book> searchByTitle(String title) {
LambdaEsQueryWrapper<Book> wrapper = new LambdaEsQueryWrapper<>();
wrapper.like(Book::getTitle, title); // 模糊匹配
return bookMapper.selectList(wrapper);
}
// 更新价格
public void updatePrice(String id, Double newPrice) {
LambdaEsUpdateWrapper<Book> wrapper = new LambdaEsUpdateWrapper<>();
wrapper.eq(Book::getId, id)
.set(Book::getPrice, newPrice);
bookMapper.update(null, wrapper);
}
// 删除书籍
public void deleteBook(String id) {
bookMapper.deleteById(id);
}
}
最佳实践:
- 使用 LambdaEsQueryWrapper 构建查询,像 MyBatis-Plus 一样链式调用(eq、like、gt、in 等)。
- 支持分页:
wrapper.limit(10, 1);(size, page)。 - 聚合查询:
wrapper.groupBy(Book::getAuthor).agg(AggType.COUNT); - 避免直接写 ES DSL,充分利用 Easy-ES 的 SQL-like 语法,提高可读性。
步骤 7: 创建 Controller 层
暴露 REST API。
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books")
@RequiredArgsConstructor
public class BookController {
private final BookService bookService;
// 新增
@PostMapping
public String add(@RequestBody Book book) {
bookService.addBook(book);
return "Added successfully";
}
// 查询所有
@GetMapping
public List<Book> getAll() {
return bookService.getAllBooks();
}
// 搜索
@GetMapping("/search")
public List<Book> search(@RequestParam String title) {
return bookService.searchByTitle(title);
}
// 更新
@PutMapping("/{id}")
public String update(@PathVariable String id, @RequestParam Double price) {
bookService.updatePrice(id, price);
return "Updated successfully";
}
// 删除
@DeleteMapping("/{id}")
public String delete(@PathVariable String id) {
bookService.deleteBook(id);
return "Deleted successfully";
}
}
步骤 8: 启动与测试
- 启动 Spring Boot 应用(
main方法)。 - ES 会自动创建索引
book_index。 - 使用 Postman 测试:
- POST /books:{“title”:”Spring Boot Guide”,”author”:”Author”,”price”:29.99,”publishDate”:”2026-01-01″}
- GET /books/search?title=Spring → 返回匹配书籍
- 检查日志,查看生成的 ES DSL 查询。
常见问题与最佳实践
- 索引管理:Easy-ES 支持自动建索引,但生产中建议手动优化映射(analyzer、分词器)。
- 性能优化:使用分页、避免全表扫描。复杂查询用 aggregation。
- 错误处理:捕获
EsException,日志记录 ES DSL。 - 多数据源:配置
easy-es.datasource支持多 ES 集群。 - 版本兼容:确保 ES 版本与 Easy-ES 匹配(官网检查)。
- 测试:使用
@EsTest注解单元测试 Mapper。 - 安全:生产中启用 ES 认证,配置用户名/密码。
- 扩展:支持自定义插件、拦截器(e.g., 审计日志)。
参考来源:(Easy-ES GitHub 官方仓库)。
这个实战覆盖了基本整合,如果你有特定场景(如聚合查询、分页),可以进一步扩展!