1. 介绍

官方文档地址:https://docs.spring.io/spring-data/elasticsearch/docs/4.1.12/reference/html/#elasticsearch.repositories

Spring Boot 使用 ElasticSearch 除了使用 es 官网建议的 RestHighLevelClient ,还可以使用 Spring Data ElasticSearch 提供的相关API。
Spring Data ElasticSearch 对 RestHighLevelClient 进行了封装,使我们使用起来更轻松。
Spring Data ElasticSearch 提供了 实现ElasticsearchRepository类和 ElasticsearchRestTemplate(es7开始) 两种用法,前者用于简单的CRUD操作,后者用于前者无法处理的复杂操作。

前提:

  • 必须根据官方文档对应的 Spring Boot 和 es 的版本进行一一对应
  • es7 和之前的改动很大,很多API都不再可用,注意变更。 | Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Boot | | —- | —- | —- | —- | | 2020.0.0[1] | 4.1.x[1] | 7.9.3 | 2.4.x[1] | | Neumann | 4.0.x | 7.6.2 | 2.3.x | | Moore | 3.2.x | 6.8.12 | 2.2.x | | Lovelace | 3.1.x | 6.2.2 | 2.1.x | | Kay[2] | 3.0.x[2] | 5.5.0 | 2.0.x[2] | | Ingalls[2] | 2.1.x[2] | 2.4.0 | 1.5.x[2] |

2. 前提配置

2.1 改pom

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>

2.2 写 yml 或 自定义 @Bean

2.2.1 写 yml

org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration 路径下寻找相关配置,并在yml中进行配置

image.png
image.png

  1. spring:
  2. elasticsearch:
  3. rest:
  4. uris:
  5. - localhost:9200
  6. - localhost:9201
  7. username: xxx # 没有可不写
  8. password: xxx # 没有可不写
  9. connection-timeout: 1s # 默认值
  10. read-timeout: 30s # 默认值

2.2.2 自定义 @Bean

同样为上面的自动装配地址,查找到相应的默认配置,并改成自己的配置

  1. // 默认自动装配源码
  2. @Configuration(
  3. proxyBeanMethods = false
  4. )
  5. @ConditionalOnMissingBean({RestHighLevelClient.class})
  6. static class RestHighLevelClientConfiguration {
  7. RestHighLevelClientConfiguration() {
  8. }
  9. @Bean
  10. RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder restClientBuilder) {
  11. return new RestHighLevelClient(restClientBuilder);
  12. }
  13. }
  1. // 自定义配置
  2. package com.edward.config;
  3. import org.apache.http.HttpHost;
  4. import org.elasticsearch.client.RestClient;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. @Configuration
  9. public class EsConfig {
  10. @Bean
  11. RestHighLevelClient restHighLevelClient() {
  12. return new RestHighLevelClient(
  13. RestClient.builder(new HttpHost("localhost", 9200)));
  14. }
  15. }

3. ElasticsearchRepository 用法

必须以上面第二步的配置为前提


3.1 Model

我们先写一个的实体类,借助这个实体类呢来完成基础的CRUD功能。

  1. @Data
  2. @Accessors(chain = true)
  3. @Document(indexName = "blog", type = "java")
  4. public class BlogModel implements Serializable {
  5. private static final long serialVersionUID = 6320548148250372657L;
  6. @Id
  7. private String id;
  8. private String title;
  9. //@Field(type = FieldType.Date, format = DateFormat.basic_date)
  10. @DateTimeFormat(pattern = "yyyy-MM-dd")
  11. @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
  12. private Date time;
  13. }

注意id字段是必须的,可以不写注解@Id。

3.2 BlogRepository

  1. public interface BlogRepository extends ElasticsearchRepository<BlogModel, String> {
  2. }

3.3 CRUD

dao层的方法除了默认了,也可以自己添加,自己添加时根据提示写出可识别的代码 或者 dao层的抽象方法上标注 @Query 注解并书写 es 查询语句

  1. @RestController
  2. @RequestMapping("/blog")
  3. public class BlogController {
  4. @Autowired
  5. private BlogRepository blogRepository;
  6. // 新增
  7. @PostMapping("/add")
  8. public Result add(@RequestBody BlogModel blogModel) {
  9. blogRepository.save(blogModel);
  10. return Result.success();
  11. }
  12. // 根据ID修改(覆盖修改)
  13. @PostMapping("/update")
  14. public Result updateById(@RequestBody BlogModel blogModel) {
  15. String id = blogModel.getId();
  16. if (StringUtils.isEmpty(id))
  17. return Result.error();
  18. blogRepository.save(blogModel);
  19. return Result.success();
  20. }
  21. // 根据ID查询
  22. @GetMapping("/get/{id}")
  23. public Result getById(@PathVariable String id) {
  24. if (StringUtils.isEmpty(id))
  25. return Result.error();
  26. Optional<BlogModel> blogModelOptional = blogRepository.findById(id);
  27. if (blogModelOptional.isPresent()) {
  28. BlogModel blogModel = blogModelOptional.get();
  29. return Result.success(blogModel);
  30. }
  31. return Result.error();
  32. }
  33. // 查询所有
  34. @GetMapping("/get")
  35. public Result getAll() {
  36. Iterable<BlogModel> iterable = blogRepository.findAll();
  37. List<BlogModel> list = new ArrayList<>();
  38. iterable.forEach(list::add);
  39. return Result.success(list);
  40. /* 分页查询(pageNum,pageSize)
  41. Page<User> users = userDao.findAll(PageRequest.of(0, 3));
  42. users.map(x -> {
  43. System.out.println(x);
  44. return null;
  45. });
  46. */
  47. }
  48. // 根据ID删除
  49. @DeleteMapping("/delete/{id}")
  50. public Result deleteById(@PathVariable String id) {
  51. if (StringUtils.isEmpty(id))
  52. return Result.error();
  53. blogRepository.deleteById(id);
  54. /*
  55. 删除所有数据
  56. blogRepository.deleteAll();
  57. */
  58. return Result.success();
  59. }
  60. }

4. ElasticsearchRestTemplate 用法

同样必须以上述2前提配置为基础 这里API较多,只写一个查询作为示例

  1. // 写法1:
  2. public List<User> testRestTemplate() {
  3. // 构建范围查找条件
  4. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(1).lte(4);
  5. // 构建 QueryBuilder
  6. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
  7. // 为 QueryBuilder 添加相应配置(范围查找条件、分页等)
  8. nativeSearchQueryBuilder.withQuery(rangeQueryBuilder);
  9. nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 2));
  10. // 搜索
  11. List<User> users = elasticsearchRestTemplate.multiGet(nativeSearchQueryBuilder.build(), User.class);
  12. return users;
  13. }
  14. // 写法2:
  15. public List<SearchHit<User>> testRestTemplate() {
  16. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(1).lte(4);
  17. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
  18. nativeSearchQueryBuilder.withQuery(rangeQueryBuilder);
  19. nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 2));
  20. SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), User.class);
  21. return searchHits.getSearchHits();
  22. }

5. 总结

  • Spring Data ElasticSearchRestHighLevelClient 要方便很多,不过要注意版本匹配和API的更新迭代。
  • 简单操作可用 ElasticsearchRepository 解决,复杂操作可用 ElasticsearchRestTemplate