Spring Boot 与 Elasticsearch 8.0 集成
Spring Boot 与 Elasticsearch 8.0 集成前言Elasticsearch 是一个功能强大的分布式搜索引擎被广泛应用于日志分析、全文搜索、监控等场景。Elasticsearch 8.0 带来了许多新特性如安全增强、性能优化、API 改进等。本文将深入探讨 Spring Boot 与 Elasticsearch 8.0 的集成方法和最佳实践帮助你构建更高效、更可靠的搜索应用。1. Elasticsearch 8.0 新特性1.1 安全增强Elasticsearch 8.0 强化了安全性默认启用了安全功能包括HTTPS 加密默认启用 HTTPS 通信内置用户认证默认创建内置用户基于角色的访问控制更细粒度的权限控制审计日志记录安全相关的操作1.2 性能优化Elasticsearch 8.0 在性能方面进行了多项优化倒排索引优化提高查询性能内存管理改进减少内存使用写入性能优化提高写入速度聚合性能改进加速聚合操作1.3 API 改进Elasticsearch 8.0 对 API 进行了改进统一的 REST API简化 API 使用新的 Java 客户端提供更强大的 Java API改进的查询 DSL更灵活的查询语法异步 API支持异步操作1.4 其他新特性数据生命周期管理更灵活的数据管理向量搜索支持向量相似度搜索自动索引管理简化索引管理改进的监控更丰富的监控指标2. Spring Boot 与 Elasticsearch 集成2.1 添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-elasticsearch/artifactId /dependency !-- 可选使用 Elasticsearch 高级客户端 -- dependency groupIdorg.elasticsearch.client/groupId artifactIdelasticsearch-rest-high-level-client/artifactId version8.0.0/version /dependency2.2 配置 Elasticsearchspring: elasticsearch: uris: https://localhost:9200 username: elastic password: your-password connection-timeout: 10000 socket-timeout: 100002.3 Elasticsearch 客户端配置Configuration public class ElasticsearchConfig { Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration ClientConfiguration.builder() .connectedTo(localhost:9200) .withBasicAuth(elastic, your-password) .withConnectTimeout(Duration.ofSeconds(10)) .withSocketTimeout(Duration.ofSeconds(10)) .withTls() .build(); return RestClients.create(clientConfiguration).rest(); } }3. 实体映射3.1 基本实体映射Document(indexName users) public class User { Id private String id; Field(type FieldType.Text) private String name; Field(type FieldType.Integer) private int age; Field(type FieldType.Text, analyzer ik_max_word) private String address; Field(type FieldType.Date) private LocalDateTime createdAt; // getters and setters }3.2 复杂实体映射Document(indexName products) public class Product { Id private String id; Field(type FieldType.Text) private String name; Field(type FieldType.Double) private double price; Field(type FieldType.Keyword) private String category; Field(type FieldType.Nested) private ListReview reviews; Field(type FieldType.Object) private Manufacturer manufacturer; // getters and setters } public class Review { Field(type FieldType.Integer) private int rating; Field(type FieldType.Text) private String comment; Field(type FieldType.Date) private LocalDateTime createdAt; // getters and setters } public class Manufacturer { Field(type FieldType.Text) private String name; Field(type FieldType.Text) private String country; // getters and setters }4. 仓库接口4.1 基本仓库接口public interface UserRepository extends ElasticsearchRepositoryUser, String { // 基于方法名的查询 ListUser findByName(String name); ListUser findByAgeBetween(int minAge, int maxAge); ListUser findByNameAndAge(String name, int age); }4.2 自定义查询public interface ProductRepository extends ElasticsearchRepositoryProduct, String { // 使用 Query 注解 Query({\bool\: {\must\: [{\match\: {\name\: \?0\}}, {\range\: {\price\: {\lte\: ?1}}}]}}) ListProduct findByNameAndPriceLessThanEqual(String name, double price); // 基于方法名的复杂查询 ListProduct findByCategoryAndReviewsRatingGreaterThan(String category, int rating); }5. 操作示例5.1 基本操作Service public class UserService { private final UserRepository userRepository; Autowired public UserService(UserRepository userRepository) { this.userRepository userRepository; } // 保存用户 public User saveUser(User user) { return userRepository.save(user); } // 根据 ID 查询用户 public OptionalUser getUserById(String id) { return userRepository.findById(id); } // 查询所有用户 public IterableUser getAllUsers() { return userRepository.findAll(); } // 删除用户 public void deleteUser(String id) { userRepository.deleteById(id); } // 根据名称查询用户 public ListUser getUsersByName(String name) { return userRepository.findByName(name); } }5.2 高级查询Service public class ProductService { private final ProductRepository productRepository; private final ElasticsearchOperations elasticsearchOperations; Autowired public ProductService(ProductRepository productRepository, ElasticsearchOperations elasticsearchOperations) { this.productRepository productRepository; this.elasticsearchOperations elasticsearchOperations; } // 复杂查询 public ListProduct searchProducts(String keyword, double maxPrice, String category) { NativeSearchQuery query new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery() .must(QueryBuilders.multiMatchQuery(keyword, name, description)) .filter(QueryBuilders.rangeQuery(price).lte(maxPrice)) .filter(QueryBuilders.termQuery(category, category))) .withSort(SortBuilders.fieldSort(price).order(SortOrder.ASC)) .withPageable(PageRequest.of(0, 10)) .build(); return elasticsearchOperations.search(query, Product.class) .stream() .map(SearchHit::getContent) .collect(Collectors.toList()); } }5.3 聚合操作Service public class AnalyticsService { private final ElasticsearchOperations elasticsearchOperations; Autowired public AnalyticsService(ElasticsearchOperations elasticsearchOperations) { this.elasticsearchOperations elasticsearchOperations; } // 按类别聚合产品 public MapString, Long getProductCountByCategory() { NativeSearchQuery query new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withAggregations(AggregationBuilders.terms(byCategory).field(category)) .build(); SearchHitsProduct searchHits elasticsearchOperations.search(query, Product.class); Terms terms searchHits.getAggregations().get(byCategory); MapString, Long result new HashMap(); for (Terms.Bucket bucket : terms.getBuckets()) { result.put(bucket.getKeyAsString(), bucket.getDocCount()); } return result; } // 计算平均价格 public double getAveragePrice() { NativeSearchQuery query new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .withAggregations(AggregationBuilders.avg(averagePrice).field(price)) .build(); SearchHitsProduct searchHits elasticsearchOperations.search(query, Product.class); Avg avg searchHits.getAggregations().get(averagePrice); return avg.getValue(); } }6. 批量操作6.1 批量索引Service public class BulkService { private final ElasticsearchOperations elasticsearchOperations; Autowired public BulkService(ElasticsearchOperations elasticsearchOperations) { this.elasticsearchOperations elasticsearchOperations; } // 批量索引文档 public void bulkIndex(ListUser users) { elasticsearchOperations.bulkIndex(users, IndexCoordinates.of(users)); } // 批量删除文档 public void bulkDelete(ListString ids) { ListDeleteQuery deleteQueries ids.stream() .map(id - { DeleteQuery deleteQuery new DeleteQuery(); deleteQuery.setId(id); return deleteQuery; }) .collect(Collectors.toList()); elasticsearchOperations.bulkDelete(deleteQueries, User.class, IndexCoordinates.of(users)); } }7. 性能优化7.1 索引优化合理设计索引根据业务需求设计合理的索引结构使用合适的字段类型选择合适的字段类型如 keyword、text、numeric 等配置分析器为文本字段配置合适的分析器设置合理的分片和副本根据数据量和查询需求设置分片和副本数量7.2 查询优化使用过滤器对不需要评分的查询使用过滤器避免深度分页使用 scroll API 或 search after 进行深度分页使用聚合缓存对频繁使用的聚合启用缓存优化查询语句避免复杂的嵌套查询7.3 写入优化使用批量操作使用 bulk API 进行批量写入合理设置刷新间隔根据业务需求设置合适的刷新间隔使用异步写入使用异步 API 进行写入操作避免实时索引对非实时数据使用延迟索引8. 最佳实践8.1 代码组织// 推荐的代码组织结构 com.example ├── entity/ // 实体类 ├── repository/ // 仓库接口 ├── service/ // 业务逻辑 ├── controller/ // 控制器 └── config/ // 配置类8.2 错误处理Service public class UserService { private final UserRepository userRepository; Autowired public UserService(UserRepository userRepository) { this.userRepository userRepository; } public User getUserById(String id) { try { return userRepository.findById(id) .orElseThrow(() - new EntityNotFoundException(User not found)); } catch (ElasticsearchException e) { throw new RuntimeException(Error querying Elasticsearch, e); } } }8.3 监控与日志management: endpoints: web: exposure: include: health,info,metrics,prometheus endpoint: health: show-details: always logging: level: org.elasticsearch.client: debug9. 案例分析9.1 全文搜索系统某电商平台使用 Elasticsearch 实现全文搜索功能主要包括商品索引将商品信息索引到 Elasticsearch全文搜索支持商品名称、描述的全文搜索过滤和排序支持按价格、类别等过滤和排序聚合分析提供商品分类统计、价格分布等分析9.2 日志分析系统某企业使用 Elasticsearch 实现日志分析系统主要包括日志收集使用 Logstash 收集应用日志日志索引将日志索引到 Elasticsearch日志查询支持按时间、级别、关键词等查询日志监控告警基于日志内容设置告警规则9.3 实时数据分析某金融机构使用 Elasticsearch 实现实时数据分析主要包括数据采集实时采集交易数据数据索引将数据索引到 Elasticsearch实时查询支持实时查询和分析可视化使用 Kibana 可视化数据10. 未来趋势10.1 向量搜索Elasticsearch 8.0 开始支持向量搜索这将为 AI 应用提供强大的支持例如语义搜索基于文本语义进行搜索图像搜索基于图像特征进行搜索推荐系统基于用户行为向量进行推荐10.2 边缘计算Elasticsearch 正在向边缘计算扩展支持在边缘设备上部署轻量级实例实现本地数据处理在边缘设备上处理数据低延迟查询减少网络延迟离线操作支持离线环境下的搜索10.3 AI 集成Elasticsearch 与 AI 技术的集成将成为未来的趋势例如智能搜索使用 AI 提高搜索准确性自动索引使用 AI 自动优化索引结构异常检测使用 AI 检测异常数据11. 总结Spring Boot 与 Elasticsearch 8.0 的集成是构建高性能搜索应用的重要组成部分。通过本文的介绍你应该对 Spring Boot 与 Elasticsearch 8.0 的集成方法和最佳实践有了更深入的了解。Elasticsearch 8.0 的新特性为我们提供了更强大的功能和更好的性能通过合理使用这些特性我们可以构建更高效、更可靠的搜索应用。结语Elasticsearch 是一个功能强大的搜索引擎它为我们提供了丰富的功能和灵活的 API。Spring Boot 与 Elasticsearch 的集成使得我们可以更方便地使用 Elasticsearch 的功能构建各种搜索和分析应用。随着 Elasticsearch 的不断发展它将为我们提供更多强大的功能帮助我们解决各种复杂的搜索和分析问题。这其实可以更优雅一点你觉得呢欢迎在评论区分享你的想法和经验