创建索引
在elasticsearch中创建students索引
PUT /students
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 2,
"index.max_ngram_diff":30,
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 30,
"token_chars": [
"letter",
"digit"
]
}
}
}
},
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text",
"analyzer": "ngram_analyzer"
},
"gender": {
"type": "keyword"
},
"birthDate": {
"type": "date",
"format": "yyyy-MM-dd"
}
}
}
}
创建项目
添加依赖
使用java操作Elasticsearce需要添加spring-boot-starter-data-elasticsearch
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>Elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Elasticsearch</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.2.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
配置yml连接Elasticsearch
spring:
elasticsearch:
rest:
uris:
- http://192.168.64.181:9200
- http://192.168.64.181:9201
- http://192.168.64.181:9202
logging:
level:
tracer: trace
创建Student类
@Document(indexName = "students", shards = 3, replicas = 2)
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Student {
/**
* 使用学号作为索引id
*/
@Id
private Long id;
private String name;
private Character gender;
/**
* es索引中的字段名,使用Field注解指定,与变量名同名可以省略
*/
@Field("birthDate")
private String birthDate;
}
注解及参数说明
@Document()
:标识要持久化到 Elasticsearch 的域对象shards
:索引indexName()的分片数。 用于创建索引。默认为1.replicas
:索引indexName()的副本数。 用于创建索引。默认为1.- `refreshInterval:索引indexName()刷新间隔,默认为1s.
indexStoreType
:索引indexName()索引存储类型,indexName
索引名称,命名要求如下:- 仅小写
- , |, (空格字符), ,, #/li>
- 不能以 -、_、+ 开头
- 不可能是 。 或者 ..
- 不能超过 255 个字节(注意它是字节,因此多字节字符将更快地计入 255 个限制)
@Id
:标识该属性为id,在 Elasticsearch 中创建文档时,使用 @Id 注解的字段作为文档的_id
值@Field
:设置字段的数据类型和其他属性。
创建StudentRepository接口继承ElasticsearchRepository接口
Spring Data 的 Repository 接口提供了一种声明式的数据操作规范,无序编写任何代码,只需遵循 Spring Data 的方法定义规范即可完成数据的 CRUD 操作。spring data es repository API只需要定义接口继承ElasticsearchRepository,基础增删改查方法,在父接口中已定义。可以通过继承ElasticsearchRepository
接口添加自定义的数据操作方法。
Repository 方法命名规范
https://www.yuque.com/yiquanchaoren-dvwhg/javassm/arwhgdvgif4s?inner=HoIhB
public interface StudentRepository extends ElasticsearchRepository<Student, Long> {
/**
* 在name字段搜索关键词
*
* @param key 搜索使用的关键词
* @return {@link List}<{@link Student}> 学生信息列表
*/
List<Student> findByName(String key);
/**
* 在name字段中搜索关键词,或者使用birthDate字段匹配指定日期
*
* @param name 名字
* @param birthDate 出生日期
* @return {@link List}<{@link Student}> 符合要求的学生信息
*/
List<Student> findByNameOrBirthDate(String name, String birthDate);
}
进行测试
@SpringBootTest
public class Test01 {
private final StudentRepository studentRepository;
@Autowired
public Test01(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
@Test
public void test1() {
//在es服务器的students索引中保存学生信息
studentRepository.save(new Student(1001L, "马大钊", '女', "0659-11-04"));
studentRepository.save(new Student(1002L, "马二钊", '女', "0659-11-05"));
studentRepository.save(new Student(1003L, "马三钊", '女', "0659-11-06"));
studentRepository.save(new Student(1004L, "马四钊", '女', "0659-11-07"));
studentRepository.save(new Student(1005L, "马五钊", '女', "0659-11-08"));
studentRepository.save(new Student(1006L, "马六钊", '女', "0659-11-09"));
studentRepository.save(new Student(1007L, "马七钊", '女', "0659-11-10"));
studentRepository.save(new Student(1008L, "马小钊", '女', "0659-11-11"));
}
@Test
public void test2() {
studentRepository.save(new Student(1001L, "马王堆", '?', "0023-11-04"));
}
@Test
public void test3() {
Optional<Student> stu = studentRepository.findById(1001L);
//判断Optional对象中是否存在Student对象
if (stu.isPresent()) {
System.out.println("-------------------------------" + stu + "---------------------------------");
}
Iterable<Student> students = studentRepository.findAll();
for (Student student : students) {
System.out.println(student);
}
}
@Test
public void test4() {
studentRepository.deleteById(1008L);
}
@Test
public void test5() {
List<Student> studentList = studentRepository.findByName("马王");
for (Student student : studentList) {
System.out.println(student);
}
}
@Test
public void test6() {
List<Student> students = studentRepository.findByNameOrBirthDate("堆", "0659-11-05");
for (Student student : students) {
System.out.println(student);
}
}
}
使用 Criteria 构建自定义查询
Criteria数据查询
- 使用Criteria封装搜索条件
- CriteriaQuery封装Criteria条件对象和分页参数
- 注入
ElasticsearchOperations
对象进行查询
创建Criteria查询类
@Component
public class StudentSearch {
private final ElasticsearchOperations operations;
@Autowired
public StudentSearch(ElasticsearchOperations operations) {
this.operations = operations;
}
/**
* 按名称搜索
*
* @param key 关键
* @return {@link List}<{@link Student}> 符合条件的学生列表
*/
public List<Student> searchByName(String key) {
Criteria criteria = new Criteria("name");
//设置条件
criteria.is(key);
return exec(criteria);
}
private List<Student> exec(Criteria criteria) {
//将搜索条件封装之Query对象
CriteriaQuery query = new CriteriaQuery(criteria);
List<Student> list = new ArrayList<>();
/*
使用ElasticsearchOperations工具类执行查询,需要进行依赖注入
SearchHit对象中包含学生数据,相关度得分
*/
SearchHits<Student> search = operations.search(query, Student.class);
for (SearchHit<Student> searchHit : search) {
Student stu = searchHit.getContent();
list.add(stu);
}
return list;
}
/**
* 根据出生日期进行搜索
*
* @param from 开始日期
* @param to 结束日期
* @return {@link List}<{@link Student}> 符合条件的学生列表
*/
public List<Student> searchByBirthDate(String from, String to) {
Criteria criteria = new Criteria("birthDate");
criteria.between(from, to);
return exec(criteria);
}
}
进行测试
@SpringBootTest
public class Test02 {
private final StudentSearch search;
@Autowired
public Test02(StudentSearch search) {
this.search = search;
}
@Test
public void test1(){
List<Student> list = search.searchByName("马");
for (Student student : list) {
System.out.println(student);
}
}
@Test
public void test2(){
List<Student> list = search.searchByBirthDate("0001-01-01", "2021-11-04");
for (Student student : list) {
System.out.println(student);
}
}
}
Criteria分页查询和高亮
分页
- Pageable—-向服务器提交的分页参数,page(页数),size(每页的记录数)
- Page ————从服务器返回的一页数据,数据列表,分页信息(可选,可直接使用List<?>)
Repository
Page<Student> findByName(String key, Pageable pageable);
Criteria
Criteria criteria = new Criteria(args);
CriteriaQuery query = new CriteriaQuery(criteria);
query.setPageable(pageable);
创建接口
public interface StudentRepository extends ElasticsearchRepository<Student, Long> {
/**
* 在name字段中搜索关键词,或者使用birthDate字段匹配指定日期进行分页查询
*
* @param name 名字
* @param birthDate 出生日期
* @param pageable 分页参数
* @return {@link List}<{@link Student}>
*/
Page<Student> findByNameOrBirthDate(String name, String birthDate, Pageable pageable);
}
进行测试
@SpringBootTest
public class Test01 {
private final StudentRepository studentRepository;
@Autowired
public Test01(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
@Test
public void test7() {
Pageable pageable = PageRequest.of(1, 2);
Page<Student> students = studentRepository.findByNameOrBirthDate("马", "0659-11-05", pageable);
System.out.println("共有几页:" + students.getTotalPages());
System.out.println("是否有上一页:" + students.hasPrevious());
System.out.println("是否有下一页:" + students.hasNext());
System.out.println("每页大小:" + students.getNumber());
for (Student student : students) {
System.out.println(student);
}
}
}