Spring Boot 4.0 整合 Elasticsearch:商品搜索与聚合分析
前言
订单列表需要按客户、状态、金额和关键词组合搜索。把所有条件都压到业务数据库,查询会越来越复杂;搜索量上来后,还需要独立读模型承担筛选和聚合。
这篇教程把订单写入 Elasticsearch,完成文档索引、读取和聚合查询。
配套源码:dvsusan/spring-boot4-demo。
最终结果

图 1:数据库是订单事实来源,Elasticsearch 是可重建的搜索读模型。
第 1 步:启动 Elasticsearch
docker compose up -d elasticsearch
curl "http://localhost:9200/_cluster/health?pretty"预期 status 为 green 或 yellow。单节点教学环境出现 yellow 通常表示副本无法分配,不一定影响查询。
第 2 步:定义搜索文档
/**
* Elasticsearch 中的订单搜索文档。
*/
@Document(indexName = "chapter4-orders")
public class OrderSearchDocument {
@Id
private String orderNo;
private String customerId;
private BigDecimal amount;
private String status;
private Instant createdAt;
}文档 ID 使用订单号,所以重复写入天然覆盖同一文档。搜索文档不是数据库实体,应该只保留筛选和展示需要的字段。
第 3 步:封装索引读写
public class OrderSearchService {
private final ElasticsearchOperations operations;
/**
* 以订单号作为文档 ID,重复消费会覆盖同一文档。
*/
public OrderSearchDocument save(OrderSearchDocument document) {
return operations.save(document);
}
public Optional<OrderSearchDocument> find(String orderNo) {
return Optional.ofNullable(
operations.get(orderNo, OrderSearchDocument.class)
);
}
}生产项目中,save 通常由订单事件消费者或 Outbox 投递任务调用,而不是在订单 HTTP 接口里同步写 ES。
第 4 步:启动应用并索引订单
mvn clean package -DskipTests
java -jar demo-web/target/demo-web-1.0.0-SNAPSHOT.jar \
--server.port=18097 \
--demo.chapter4.elasticsearch.enabled=true先创建订单:
curl -X POST "http://localhost:18097/api/v1/orders" \
-H "Content-Type: application/json" \
-d '{"customerId":"C1003","amount":128.00}'使用返回的订单号写入索引:
curl -X POST \
"http://localhost:18097/api/v1/chapter4/search/orders/SO..."
curl \
"http://localhost:18097/api/v1/chapter4/search/orders/SO..."第二条请求读取的是 Elasticsearch 文档。
第 5 步:用 DSL 做筛选和聚合
下面查询按客户过滤,并统计状态分布:
curl -X POST "http://localhost:9200/chapter4-orders/_search?pretty" \
-H "Content-Type: application/json" \
-d '{
"size": 0,
"query": {
"term": {
"customerId": "C1003"
}
},
"aggs": {
"by_status": {
"terms": {
"field": "status"
}
}
}
}'size: 0 表示只取聚合结果,不返回文档明细。正式搜索还要设计分词器、keyword 子字段、排序字段和分页上限。
索引一致性怎么处理?
Elasticsearch 是搜索读模型,不是订单事实来源:
- 数据库事务提交后再发布索引事件。
- 使用订单号作为文档 ID,保证重复消费幂等。
- 索引失败可重试,不能回滚已经成功的订单。
- 全量重建必须可执行,防止字段映射升级后无法恢复。
- 搜索页面要标明索引延迟或提供回源查询。
常见问题排查
| 现象 | 原因 | 处理方式 |
|---|---|---|
| 连接被拒绝 | Elasticsearch 未启动 | 检查 9200 和容器日志 |
| 写入后立刻查不到 | refresh 间隔与索引延迟 | 消费端可见后查询或稍后重试 |
| 中文搜索效果差 | 使用默认分词器 | 配置合适的中文分词与映射 |
| 映射冲突 | 同一字段类型变化 | 用新索引和别名切换 |
| 搜索与数据库不一致 | 索引事件失败 | 重试、核对、全量重建 |
练习题
增加按 createdAt 时间范围过滤,并统计每个客户订单金额总和。
总结
Elasticsearch 用独立读模型换来了组合搜索和聚合能力。可靠性来自可重建、幂等索引和延迟监控,而不是把 ES 当作第二份主数据。
完成本章后,订单项目已经具备缓存、并发控制、异步消息、可靠消息、调度和搜索能力。
上一节:Quartz 定时任务
下一节:MinIO 文件存储
返回课程目录
13 个企业级实战项目 · 源码 + 教程 + 答疑
简历包装指导AI Agent 实战高并发·微服务Offer 导向持续更新3000+ 同行交流1V1 答疑3 天包退
覆盖高并发、微服务、分布式与 AI Agent:100万QPS短链、企业智能知识库、商城微服务、SaaS点餐、秒杀、刷题小程序、代码生成器、AI Agent 等。券后 ¥129(原价 ¥159),不满意 3 天包退。
