0、准备
1、es准备:
https://www.elastic.co/cn/downloads/past-releases#elasticsearch下载对应的7.6.2版本。
下载后自己安装,测试的话,主要就是配置 vim ./config/elasticsearch.yml
nohup ./bin/elasticsearch &
PS:有问题小伙伴,可以查看最后FAQ,所有博主遇见的问题都已经详细写出,保证可以启动。😄
启动es成功
2、kibana准备
下载kibana
https://www.elastic.co/cn/downloads/past-releases/kibana-7-6-2
配置vim config/kibana.yml 后自己启动。
nohup ./bin/kibana &
PS:有问题小伙伴,可以查看最后FAQ,所有博主遇见的问题都已经详细写出,保证可以启动。😄
启动并连接es成功
输入网址:http://hostname:5601
3、springboot准备
官网地址,想查看详细信息的请点击查看:https://docs.spring.io/spring-boot/docs/2.3.7.RELEASE/reference/pdf/spring-boot-reference.pdf
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
一、总览
springboot提供了多种客户端:
- 底层级别和上层级别的restclient
- ReactiveElasticsearchClient
二、实战
1、Rest Clients方式(推荐)
在appliciation.properties中加入
spring.elasticsearch.rest.uris=https://host166:9200
spring.elasticsearch.rest.read-timeout=10s
#spring.elasticsearch.rest.username=user
#spring.elasticsearch.rest.password=secret
注意:7.6.2默认端口为9200,不是9300
2、Reactive Rest Clients方式
在appliciation.properties中加入,唯一区别就是属性不一样:
spring.data.elasticsearch.client.reactive.endpoints=host:9200
spring.data.elasticsearch.client.reactive.use-ssl=true
spring.data.elasticsearch.client.reactive.socket-timeout=10s
spring.data.elasticsearch.client.reactive.username=user
spring.data.elasticsearch.client.reactive.password=secret
3、注入ElasticsearchRestTemplate
@Service
public class EsServiceImpl {
private final ElasticsearchRestTemplate template;
public EsServiceImpl(ElasticsearchRestTemplate template) {
this.template = template;
}
}
默认情况下,ElasticsearchRestTemplate内部调用的是高级别的rest client方式:
public class ElasticsearchRestTemplate extends AbstractElasticsearchTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchRestTemplate.class);
private RestHighLevelClient client;
private ElasticsearchExceptionTranslator exceptionTranslator;
// region Initialization
public ElasticsearchRestTemplate(RestHighLevelClient client) {
Assert.notNull(client, "Client must not be null!");
this.client = client;
this.exceptionTranslator = new ElasticsearchExceptionTranslator();
initialize(createElasticsearchConverter());
}
。。。
}
4、CRUD
要看详细的client操作,需要跳转到spring-data-elasticsearch中去:
总体来说,主要包含两种方式:
-
Elasticsearch Operations 较为底层,主要使用ElasticsearchRestTemplate,该方法较为灵活是最新引入,本文主要使用该种方式,集成了多种操作
-
Elasticsearch Repositories较为高层,主要使用dao继承ElasticsearchRepository类,该方法快捷,方便,资料较多,网上可查。
实体entity
@Data
@Builder
public class Info {
/**
* 提供给ElasticsearchRestTemplate作为主键,可以不写
*/
@Id
private String mid;
private String uid;
private String ar;
private String ch;
private String vc;
private String dt;
private String hr;
private String mi;
private Long ts;
}
4.1、保存
public Object save(String date) {
IndexCoordinates index = IndexCoordinates.of(String.format("%s%s%s", INDEX_PREFIX, date, INDEX_SUBFIX));
final String id = UUID.randomUUID().toString();
final LocalDateTime now = LocalDateTime.now();
final Info info = Info.builder()
.ar("地址" + id)
.ch("渠道" + id)
.dt(date)
.hr(String.valueOf(now.getHour()))
.mi(String.valueOf(now.getMinute()))
.mid(id)
.ts(now.toEpochSecond(ZoneOffset.ofHours(8)))
.uid(id)
.vc(id).build();
return template.save(info,index);
}
4.2、查询
public Object queryByDate(String date) {
IndexCoordinates index = IndexCoordinates.of(String.format("%s%s%s", INDEX_PREFIX, date, INDEX_SUBFIX));
final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchAllQuery())
.withPageable(PageRequest.of(0, 10))
.build();
//注意这里是searchScrollStart
SearchScrollHits<Info> scroll = template.searchScrollStart(1000, searchQuery, Info.class, index);
List<String> ids = new ArrayList<>();
List<Info> sampleEntities = new ArrayList<>();
while (scroll.hasSearchHits()) {
sampleEntities.addAll(scroll.get().map(SearchHit::getContent).collect(Collectors.toList()));
String scrollId = scroll.getScrollId();
ids.add(scrollId);
//注意这里是searchScrollContinue
scroll = template.searchScrollContinue(scrollId, 1000, Info.class, index);
}
template.searchScrollClear(ids);
return sampleEntities;
}
FAQ
1、启动elasticsearch失败
2、ElasticsearchRestTemplate连接失败
2020-12-29 18:07:01.859 ERROR 15468 --- [nio-8070-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Unrecognized SSL message, plaintext connection?; nested exception is java.lang.RuntimeException: Unrecognized SSL message, plaintext connection?] with root cause
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
注意这里 spring.elasticsearch.rest.uris=https://host166:9200,使用http协议
3、链接ElasticsearchRestTemplate连接失败
2020-12-29 20:02:21.916 ERROR 16520 --- [nio-8070-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.elasticsearch.UncategorizedElasticsearchException: Elasticsearch exception [type=cluster_block_exception, reason=blocked by: [SERVICE_UNAVAILABLE/1/state not recovered / initialized];]; nested exception is ElasticsearchStatusException[Elasticsearch exception [type=cluster_block_exception, reason=blocked by: [SERVICE_UNAVAILABLE/1/state not recovered / initialized];]]] with root cause
org.elasticsearch.ElasticsearchStatusException: Elasticsearch exception [type=cluster_block_exception, reason=blocked by: [SERVICE_UNAVAILABLE/1/state not recovered / initialized];]
4、kibana链接报错
检查端口注意:7.6.2默认端口为9200,不是9300
5、elasticsearch启动报错
[2020-12-30T09:20:03,213][WARN ][o.e.c.c.ClusterFormationFailureHelper] [node-166] master not discovered yet, this node has not previously joined a bootstrapped (v7+) cluster, and [cluster.initial_master_nodes] is empty on this node: have discovered [{node-166}{sZZicbtfSNyTaPuJX_sjwg}{yqATmGVlRnS2zYcLDX9S2Q}{10.120.9.132}{10.120.9.132:9300}{dilm}{ml.machine_memory=47305478144, xpack.installed=true, ml.max_open_jobs=20}]; discovery will continue using [] from hosts providers and [{node-166}{sZZicbtfSNyTaPuJX_sjwg}{yqATmGVlRnS2zYcLDX9S2Q}{10.120.9.132}{10.120.9.132:9300}{dilm}{ml.machine_memory=47305478144, xpack.installed=true, ml.max_open_jobs=20}] from last-known cluster state; node term 0, last-accepted version 0 in term 0
配置 config/elasticsearch.yml 中的cluster.initial_master_nodes,注意这个信息和自己写的【node-name】一致
技术交流