0%

Springboot3整合elasticsearch8.0.x(上)

前言

在使用springboot2.0.x时,整合elasticsearch,更多的是使用es提供的高级客户端RestHighLevelClient。在elasticsearch8后好多都被标注为过时了。

本文主要基于Springboot3,对Elasticsearch的索引、文档进行操作。版本信息如下:

1
2
3
JDK版本: JDK17
Springboot版本:3.0.2
Elasticsearch:8.5.3

PS: springbootElasticsearch的版本对应关系参考Spring官网-https://docs.spring.io/spring-data/elasticsearch/reference/elasticsearch/versions.html

前置工作

  • 安装Elasticsearch

使用的是docker镜像,拉取镜像: docker pull elasticsearch:8.5.3

启动Elasticsearch,将配置文件和插件目录都挂载到外部文件夹:

1
2
3
4
5
6
7
docker run --name elasticsearch --restart=always --privileged -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d docker.elastic.co/elasticsearch/elasticsearch:8.5.3

es默认开启了SSL认证,可以修改配置文件或使用https访问9200端口,输入用户名和密码。为了方便,直接注掉下面配置文件,关闭安全认证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Enable security features
xpack.security.enabled: false #修改为false

xpack.security.enrollment.enabled: true

# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
xpack.security.http.ssl:
enabled: false #修改为false
# keystore.path: certs/http.p12 #注掉

# Enable encryption and mutual authentication between cluster nodes
xpack.security.transport.ssl:
enabled: false
# 注掉下面配置
# verification_mode: certificate
# keystore.path: certs/transport.p12
# truststore.path: certs/transport.p12
#----------------------- END SECURITY AUTO CONFIGURATION -------------------------

重新启动即可

  • 准备数据

这里用的是GitHub提供的测试数据,GitHub链接:https://github.com/elastic/elasticsearch/blob/7.5/docs/src/test/resources/accounts.json

直接使用postman调用REST API创建索引和文档

  1. 创建索引,索引名为bank

POST请求: http://${IP}:9200/bank/

  1. 批量创建文档

PUT请求:http://${IP}:9200/bank/_bulk

请求体复制GitHub文件里面的数据就可以,如果请求报错,在请求体最后一行回车一下加个空行就行

  1. 测试

使用bank_search查询数据看看插入成功没

整合Springboot

引入依赖:

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

添加配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class MyElasticsearchConfiguration extends ElasticsearchConfiguration {
// es的访问地址
@Value("${es.host}")
private String url;

@Override
public @NotNull ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo(url)
.build();
}
}

这样就可以了。。。

索引创建

新建一个实体类, 注解@Document中有一个属性boolean createIndex() default true;

会自动创建索引。

注解Field用来标注字段的类型、是否可以被搜索等。

并且可以指定作为id的字段,使用注解org.springframework.data.annotation.Id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import lombok.Data;
import lombok.ToString;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Data
@Document(indexName = "bank")
@ToString
public class Balance {
@Field(type = FieldType.Long, name = "account_number")
@Id //指定该字段作为id
private long accountNumber;
@Field(type = FieldType.Text)
private String address;
@Field(type = FieldType.Text)
private String firstname;
@Field(type = FieldType.Text)
private String lastname;
@Field(type = FieldType.Long)
private long age;
@Field(type = FieldType.Text)
private String gender;
@Field(type = FieldType.Text)
private String employer;
@Field(type = FieldType.Text)
private String email;
@Field(type = FieldType.Text)
private String city;
@Field(type = FieldType.Text)
private String state;
@Field(type = FieldType.Long)
private long balance;
}

使用ElasticsearchTemplate

Spring官网中描述了Spring对ES操作的一些接口定义,分别如下:

1
2
3
4
5
6
7
IndexOperations      索引操作,例如:创建、删除

DocumentOperations 文档操作,存储、基于id的更新、获取

SearchOperations 查询

ElasticsearchOperations 整合了文档和查询操作

ElasticsearchTemplate封装了所有ES操作。使用时只需注入即可

1
2
@Autowired
ElasticsearchTemplate template;

索引

使用indexOps方法获取索引操作对象IndexOperations

1
IndexOperations indexOperations = elasticsearchTemplate.indexOps(Balance.class);

判断索引是否存在

1
2
3
4
@Test
void indexExistsTest() {
Assertions.assertTrue(indexOperations.exists());
}

创建索引

1
2
3
4
@Test
void indexCreateTest() {
Assertions.assertTrue(indexOperations.create());
}

删除索引

1
2
3
4
@Test
void indexDeleteTest() {
Assertions.assertTrue(indexOperations.delete());
}

文档

使用save方法保存或更新文档

可以根据定义的ES的实体类,我们new一个对象并设置好属性值,然后调用save方法进行保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
void saveMethodTest() {
Balance balance = new Balance();
balance.setBalance(14000);
balance.setCity("Shen Zhen");
balance.setAge(25);
balance.setEmail("xxx@github.com");
balance.setAddress("Shennan Street");
balance.setEmployer("none");
balance.setFirstname("bryant");
balance.setGender("gender");
balance.setState("UT");
balance.setLastname("kobe");
balance.setAccountNumber(8888);
Balance save = elasticsearchTemplate.save(balance);
}

更新是一样的,指定对应ID,调用save方法即为更新。

使用delete方法删除文档

可以像Mysql那样传入Query对象,根据条件进行删除,也可以直接指定Id,根据id删除文档。Query后面再讲,这里只说根据id删除,直接调用方法即可

1
2
3
4
5
6
7
@Test
void documentDeleteTest() {
String deleteId = elasticsearchTemplate.delete("8888", Balance.class);
Assertions.assertEquals(deleteId, "8888");
Balance balance = elasticsearchTemplate.get("8888", Balance.class);
Assertions.assertNull(balance);
}
使用ElasticsearchRepoistory

作为Spring Data的一份子,自然可以使用JPA那一套,看源码,ElasticsearchRepoistory继承了支持curd和分页排序的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
@NoRepositoryBean
public interface ElasticsearchRepository<T, ID> extends PagingAndSortingRepository<T, ID>, CrudRepository<T, ID> {

/**
* Search for similar entities using a morelikethis query
*
* @param entity the entity for which similar documents should be searched, must not be {@literal null}
* @param fields
* @param pageable , must not be {@literal null}
* @return
*/
Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable);
}

因此,也可以定义自己的接口,只需继承ElasticsearchRepository即可, 因为我们指定了accountNumber作为我们的id,所以泛型指定Long根据某个字段查询一般都是findByxxx,具体用法参考JPA

1
2
3
4
5
6
7
8
public interface BalanceRepository extends ElasticsearchRepository<Balance, Long> {
/**
* 根据地址模糊查询
* @param address
* @return
*/
List<Balance> findByAddressLike(String address);
}

接下来我们就可以按照JPA的规定直接保存、删除、获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  
// 保存方法
@Test
void saveByRepoTest() {
Balance balance = new Balance();
balance.setBalance(19999);
balance.setCity("Canton");
balance.setAge(25);
balance.setEmail("xxx@gmail.com");
balance.setAddress("Lin He Xi");
balance.setEmployer("none");
balance.setFirstname("Ng");
balance.setGender("gender");
balance.setState("UT");
balance.setLastname("Ron");
balance.setAccountNumber(6666);
Balance save = balanceRepository.save(balance);
// 注意重新Equals方法和HashCode方法
Assertions.assertEquals(save, balance);
}

// findByxxx
@Test
void findByIdTest() {
Optional<Balance> optional = balanceRepository.findById(6666L);
Assertions.assertTrue(optional.isPresent());
Balance balance = optional.get();
System.out.println(balance);
}

@Test
void findByAddressLikeTest() {
List<Balance> veterans = balanceRepository.findByAddressLike("Veterans");
veterans.forEach(System.out::println);
}


Spring官网介绍了几种不同的查询方式,都是实现了Query接口,可以实现各种复杂的查询操作。下篇再讲~

-------------本文结束感谢您的阅读-------------