1.依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/>
</parent>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!--spring boot and web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--spring data elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
</dependencies>
2.yaml
spring:
elasticsearch:
uris: http://10.43.119.175:9200
username: elastic
password: hXtO*Lzi2GGJ5wUmUA2c
3.索引类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "video")
public class VideoDTO {
/**
* type 对应Elasticsearch中属性类型,使用FiledType枚举快速获取。
* text 类型能被分词
* keywords 不能被分词
* index 是否创建索引,作为搜索条件时index必须为true
* analyzer 指定分词器类型。
*/
@Id
@Field(type = FieldType.Text, index = false)
private Long id;
@Field(type = FieldType.Text)
private String title;
@Field(type = FieldType.Text)
private String description;
@Field(type = FieldType.Keyword)
private String category;
@Field(type = FieldType.Integer)
private Integer duration;
@Field(type = FieldType.Date, format = DateFormat.date_hour_minute_second)
private LocalDateTime createTime;
public VideoDTO(Long id, String title, String description, Integer duration,String category) {
this.id = id;
this.title = title;
this.description = description;
this.duration = duration;
this.createTime = LocalDateTime.now();
this.category = category;
}
}
4.测试类
/**
* Spring Data:用于简化数据访问和持久化的开发框架,提供了一组统一的 API 和抽象
* 与各种数据存储技术(如关系型数据库、NoSQL 数据库、Elasticsearch 等)进行交互变得更加容易
*/
/**
* Java API Client(8.X版本开始推荐使用):是一个用于与Elasticsearch服务器进行通信的Java客户端库
* 封装了底层的Transport通信,并提供了同步和异步调用、流式和函数式调用等方法
* Java REST Client: 7.1版本之前使用的Java客户端是
*/
@Service
public class EsTest {
@Autowired
private ElasticsearchTemplate restTemplate;
/**
* 判断索引是否存在索引
*/
public void existsIndex() {
IndexOperations indexOperations = restTemplate.indexOps(VideoDTO.class);
boolean exists = indexOperations.exists();
System.out.println(exists);
}
/**
* 创建索引
*/
public void createIndex() {
// spring data es所有索引操作都在这个接口
IndexOperations indexOperations = restTemplate.indexOps(VideoDTO.class);
// 是否存在,存在则删除
if(indexOperations.exists()){
indexOperations.delete();
}
// 创建索引
indexOperations.create();
//设置映射: 在正式开发中,几乎不会使用框架创建索引或设置映射,这是架构或者管理员的工作,不适合使用代码实现
restTemplate.indexOps(VideoDTO.class).putMapping();
}
/**
* 删除索引
*/
public void deleteIndex() {
IndexOperations indexOperations = restTemplate.indexOps(VideoDTO.class);
boolean delete = indexOperations.delete();
System.out.println(delete);
}
/**
* 添加
*/
public void insert(){
VideoDTO videoDTO = new VideoDTO();
videoDTO.setId(1L);
videoDTO.setTitle("小滴课堂架构大课和Spring Cloud");
videoDTO.setCreateTime(LocalDateTime.now());
videoDTO.setDuration(100);
videoDTO.setCategory("后端");
videoDTO.setDescription("这个是综合大型课程,包括了jvm,redis,新版spring boot3.x,架构,监控,性能优化,算法,高并发等多方面内容");
VideoDTO saved = restTemplate.save(videoDTO);
System.out.println(saved);
}
/**
* 更新
*/
public void update(){
VideoDTO videoDTO = new VideoDTO();
videoDTO.setId(1L);
videoDTO.setTitle("小滴课堂架构大课和Spring Cloud V2");
videoDTO.setCreateTime(LocalDateTime.now());
videoDTO.setDuration(102);
videoDTO.setCategory("后端");
videoDTO.setDescription("这个是综合大型课程,包括了jvm,redis,新版spring boot3.x,架构,监控,性能优化,算法,高并发等多方面内容");
VideoDTO saved = restTemplate.save(videoDTO);
System.out.println(saved);
}
/**
* 批量添加
*/
public void batchInsert() {
List<VideoDTO> list = new ArrayList<>();
list.add(new VideoDTO(2L, "老王录制的按摩课程", "主要按摩和会所推荐", 123, "后端"));
list.add(new VideoDTO(3L, "冰冰的前端性能优化", "前端高手系列", 100042, "前端"));
list.add(new VideoDTO(4L, "海量数据项目大课", "D哥的后端+大数据综合课程", 5432345, "后端"));
list.add(new VideoDTO(5L, "小滴课堂永久会员", "可以看海量专题课程,IT技术持续充电平台", 6542, "后端"));
list.add(new VideoDTO(6L, "大钊-前端低代码平台", "高效开发底层基础平台,效能平台案例", 53422, "前端"));
list.add(new VideoDTO(7L, "自动化测试平台大课", "微服务架构下的spring cloud架构大课,包括jvm,效能平台", 6542, "后端"));
Iterable<VideoDTO> result = restTemplate.save(list);
System.out.println(result);
}
/**
* 主键查询
*/
public void searchById(){
VideoDTO videoDTO = restTemplate.get("3", VideoDTO.class);
assert videoDTO != null;
System.out.println(videoDTO);
}
/**
* 删除ById
*/
public void deleteById() {
String delete = restTemplate.delete("2", VideoDTO.class);
System.out.println(delete);
}
/**
* NativeQuery
* 搜索复杂查询或无法使用CriteriaAPI 表达的查询时使用的类,例如在构建查询和使用聚合的场景
*/
/**
* 查询所有:
*/
public void searchAll(){
SearchHits<VideoDTO> search = restTemplate.search(Query.findAll(), VideoDTO.class);
List<SearchHit<VideoDTO>> searchHits = search.getSearchHits();
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHits.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
/**
* match查询
*/
public void matchQuery(){
Query query = NativeQuery.builder().withQuery(q -> q
.match(m -> m
.field("description") //字段
.query("spring") //值
)).build();
SearchHits<VideoDTO> searchHits = restTemplate.search(query, VideoDTO.class);
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHits.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
/**
* 分页查询
*/
public void pageSearch() {
Query query = NativeQuery.builder().withQuery((co.elastic.clients.elasticsearch._types.query_dsl.Query) Query.findAll())
.withPageable(Pageable.ofSize(3).withPage(0)).build();
SearchHits<VideoDTO> searchHits = restTemplate.search(query, VideoDTO.class);
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHits.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
/**
* 排序查询,根据时长降序排列
*/
public void sortSearch() {
Query query = NativeQuery.builder().withQuery((co.elastic.clients.elasticsearch._types.query_dsl.Query) Query.findAll())
.withPageable(Pageable.ofSize(10).withPage(0))
// descending():倒叙 ascending():默认的,正序
.withSort(Sort.by("duration").descending()).build();
SearchHits<VideoDTO> searchHits = restTemplate.search(query, VideoDTO.class);
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHits.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
/**
* StringQuery搜索:将Elasticsearch查询作为JSON字符串
*/
public void stringQuery() {
//搜索标题有 架构 关键词,描述有 spring关键字,时长范围是 10~6000之间的
String dsl = """
{"bool":{"must":[{"match":{"title":"架构"}},{"match":{"description":"spring"}},{"range":{"duration":{"gte":10,"lte":6000}}}]}}
""";
Query query = new StringQuery(dsl);
List<SearchHit<VideoDTO>> searchHitList = restTemplate.search(query, VideoDTO.class).getSearchHits();
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHitList.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
/**
* 聚合查询
* CriteriaQuery
* 创建Criteria来搜索数据,而无需了解 Elasticsearch 查询的语法或基础知识
* 允许用户通过简单地连接和组合,指定搜索文档必须满足的对象来构建查询
*/
void aggQuery() {
Query query = NativeQuery.builder()
.withAggregation("category_group", Aggregation.of(a -> a
.terms(ta -> ta.field("category").size(2))))
.build();
SearchHits<VideoDTO> searchHits = restTemplate.search(query, VideoDTO.class);
//获取聚合数据
ElasticsearchAggregations aggregationsContainer = (ElasticsearchAggregations) searchHits.getAggregations();
Map<String, ElasticsearchAggregation> aggregations = Objects.requireNonNull(aggregationsContainer).aggregationsAsMap();
//获取对应名称的聚合
ElasticsearchAggregation aggregation = aggregations.get("category_group");
Buckets<StringTermsBucket> buckets = aggregation.aggregation().getAggregate().sterms().buckets();
//打印聚合信息
buckets.array().forEach(bucket -> {
System.out.println("组名:"+bucket.key().stringValue() + ", 值" + bucket.docCount());
});
// 获得searchHits,进行遍历得到content
List<VideoDTO> videoDTOS = new ArrayList<>();
searchHits.forEach(hit -> {
videoDTOS.add(hit.getContent());
});
System.out.println(videoDTOS);
}
}
5.接口
@RestController
@RequestMapping("/test")
public class TestAPI {
@Autowired
private EsTest esTest;
@PostMapping("/test")
public String test(){
esTest.createIndex();
esTest.deleteIndex();
return "test";
}
}