这一将主要讲如何用springboot整合elasticsearch
spring data整合了许多数据库的相关操作,比如redis,mongdb等等,那么如何使用spring data es呢
环境 es5.6.8 springboot2.0.1
工具 swagger lombok
官方文档地址
为了防止相关依赖引起的错误,请大家用官网推荐的整合版本
- 创建maven工程,导入以下依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<properties>
<spring.boot.version>2.0.1.RELEASE</spring.boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<swagger.version>2.7.0</swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
</dependencies>
- 创建目录结构
- 创建实体Article
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "blog4",type = "article")
public class Article {
@Id
@Field(type = FieldType.Integer,store = true,index = false)
private Integer id;
@Field(index = true,analyzer = "ik_smart",searchAnalyzer = "ik_smart",store = true,type = FieldType.text)
private String title;
@Field(index = true,analyzer = "ik_smart",searchAnalyzer = "ik_smart",store = true,type = FieldType.text)
private String content;
}
- 创建ArticleRepository
这里泛型的第一个参数是指对应的实体,第二个是对应的主键类型
ElasticsearchRepository<>中封装了常用的crud方法
public interface ArticleRepository extends ElasticsearchRepository<Article,Integer> {
}
- 创建响应dto,这个类主要是为了给客户端统一的响应结果
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResponseDto<T> {
private int code;
private boolean success;
private T data;
public static ResponseDto getInstance(int code,boolean success,Object data){
return new ResponseDto<>(code,success,data);
}
}
- swagger配置类,与启动类同目录
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
////为当前包路径
.apis(RequestHandlerSelectors.basePackage("com.edou.es.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot中使用Swagger2构建RESTful APIs")
.version("1.0")
.build();
}
}
- application.yml 这里我本地使用了集群,对应三个结点
- 创建controller 保存一条数据 默认save之前springboot会根据Article的注解信息帮我们创建index type mapping等
这里注入了ArticleRepository 和 ElasticsearchTemplate,前者用起来更方便,后者更接近es原生操作方式
- 查询(根据id)
//查询
@ApiOperation(value = "根据id查询",notes = "传入id")
@GetMapping("/find")
public ResponseDto<Article> find(Integer id){
Optional<Article> byId = articleRepository.findById(id);
if(byId.isPresent()){
return ResponseDto.getInstance(200,true,byId.get());
}
return ResponseDto.getInstance(404,false,null);
}
- 删除 根据id
这里虽然调用的delete方法传入的是一个实体对象,底层还是根据id删除的,我尝试只传入title会报以下错误
//删除
@ApiOperation(value = "删除一条",notes = "传入id")
@PostMapping("/delete")
public ResponseDto<Article> delete(Integer id){
articleRepository.delete(Article.builder().id(id).build());
return ResponseDto.getInstance(200,true,null);
}
- 分页查询
这里需要注意page-1,如果传入的是页码,记得要-1,es是从0开始查的,第一页就相当于从第0开始查
@ApiOperation(value = "分页查",notes = "传入分页参数")
@GetMapping("/findPage")
public ResponseDto findAll(int page,int size){
PageRequest of = PageRequest.of(page-1, size);
Page<Article> all = articleRepository.findAll(of);
if(all.hasContent()){
return ResponseDto.getInstance(200,true,all.getContent());
}
return ResponseDto.getInstance(400,false,null);
}
- repository接口自定义方法
spring data es为我们整合了许多条件关键词,只要按照一定的规则写方法名就可以实现复杂查询,也可以通过querybuilders自己构造查询条件
- 根据title term/querystring查询(默认使用的是term比如findByTitle)
@ApiOperation(value = "根据title查",notes = "传入title")
@GetMapping("/find/{title}")
public ResponseDto findByTitle(@PathVariable String title){
Iterable<Article> title1 = articleRepository.search(QueryBuilders.queryStringQuery(title).defaultField("title"));
List<Article> lists = new ArrayList<>();
title1.forEach(lists::add);
if(!CollectionUtils.isEmpty(lists)){
return ResponseDto.getInstance(200,true,lists);
}
return ResponseDto.getInstance(400,false,null);
/*List<Article> byTitle = articleRepository.findByTitle(title);
if(!CollectionUtils.isEmpty(byTitle)){
return ResponseDto.getInstance(200,true,byTitle);
}
return ResponseDto.getInstance(400,false,null);*/
}
- 根据title分页查询
这里我使用了三种方法,第一种是根据我们在repository接口定义的方法,第二种是调用repository的search方法,这个方法需要传入QueryBuilder类型的参数,而使用QueryBuilders的很多静态方法也能满足我们的查询条件,第三种是使用elasticsearchtemplate的方法,构造SearchQuery。
展示