0
点赞
收藏
分享

微信扫一扫

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)


文章目录

  • ​​一、环境搭建​​
  • ​​1、相关文档、链接​​
  • ​​2、软件安装​​
  • ​​(1)安装 Elasticsearch​​
  • ​​(2)安装 Head​​
  • ​​(3)安装 IK 分词器​​
  • ​​(4)安装 Kibana​​
  • ​​二、SpringBoot 搭建 ES 环境​​
  • ​​1、SpringBoot 集成 ES​​
  • ​​2、概念入门思想​​
  • ​​三、Elasticsearch 官方文档 API​​
  • ​​1、索引 API​​
  • ​​(1)创建索引​​
  • ​​(2)索引是否存在​​
  • ​​(3)获取索引​​
  • ​​(4)删除索引​​
  • ​​2、文档 API​​
  • ​​(1)添加文档​​
  • ​​(2)文档是否存在​​
  • ​​(3)获取文档​​
  • ​​(4)更新文档​​
  • ​​(4)删除文档​​
  • ​​3、批量 API​​
  • ​​(1)批量导入数据​​
  • ​​(2)查询数据​​
  • ​​(3)查询数据-分页​​
  • ​​(3)查询数据-高亮​​

Hello,各位小伙伴们,最近忙于公司项目,没有太多的时间分享技术文档,今天抽空学习一下 Elasticsearch 这门搜索引擎技术。在大数据时代,不会搜索引擎确实有点说不过去,下面我们通过简单的实战,让各位小伙伴上手这个 elasticsearch 搜索引擎,能达到企业级的实战水准

一、环境搭建

1、相关文档、链接

有部分地址是使用的华为镜像地址下载的,国内的速度快,https://mirrors.huaweicloud.com

官方文档

  • 官方所有文档:​​https://www.elastic.co/guide/en/elasticsearch/reference/index.html​​
  • 官方 7.9.x 文档:​​https://www.elastic.co/guide/en/elasticsearch/reference/7.6/index.html​​
  • Java REST Client (deprecated):​​https://www.elastic.co/guide/en/elasticsearch/client/java-rest/index.html​​
  • elasticsearch 官方文档的 API 列表:​​https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-supported-apis.html​​

下载地址,找到对应的版本,直接点击下载即可,我这里统一使用的是 7.6.1

  • elasticsearch 下载地址:​​https://repo.huaweicloud.com/elasticsearch/​​
  • IK 分词器下载地址:​​https://github.com/medcl/elasticsearch-analysis-ik​​
  • kibana 下载地址:​​https://mirrors.huaweicloud.com/kibana/​​
  • elasticsearch-head 下载地址:​​https://github.com/mobz/elasticsearch-head​​
  • logstash 下载地址:​​https://mirrors.huaweicloud.com/logstash/​​

也有最新版本,但是为了稳定长时间使用,建议还是使用同一个版本,有哪些坑,哪些潜在问题,用多了自然就熟练了,有时间再多研究新版本

2、软件安装

本片文章讲解 Windows 环境下的操作,Linux 环境下搭建 ES 环境,会在 Linux 系列文章中说明。下载完所有软件之后,如下所示

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_elasticsearch

(1)安装 Elasticsearch

Elasticsearch 安装很简单,直接解压,找到 bin/elasticsearch.bat 双击启动就可以了

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_ik分词器_02

日志中有这么一句话

[2022-07-27T10:31:20,865][INFO ][o.e.h.AbstractHttpServerTransport] [DESKTOP-ITMR1G0] publish_address {127.0.0.1:9200}, bound_addresses {127.0.0.1:9200}, {[::1]:9200}

也就是说发布的地址是:http://127.0.0.1:9200,浏览器直接访问这个地址即可,如下所示

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_head插件_03

Elasticsearch 就安装完成啦

  • 如果电脑配置不是很高,可以修改一下 ES 使用的内存,默认是 1G,修改 elasticsearch/confi/jvm.options 文件

-Xms1g
-Xmx1g

(2)安装 Head

Github 地址是:​​https://github.com/mobz/elasticsearch-head​​,通过上面的地址直接下载了之后解压,有多种运行 elasticsearch-head 的方法。

下载依赖慢的,可以使用淘宝镜像地址,也就是 cnpm 下载,这里我就不做过多阐述

  • 使用内置服务器运行,访问地址:http://localhost:9100/

git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
open

这将启动一个在端口 9100 上运行的本地网络服务器,服务于 elasticsearch-head

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_kibana_04


点击上面的连接,发现连接不上,打开 F12 控制台,发现疯狂报错跨域

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_elasticsearch_05


找到 elasticsearch-7.6.1/config/elasticsearch.yml 配置文件,在末尾添加跨域支持,然后重启 Elasticsearch

# 支持跨域访问
http.cors.enabled: true
http.cors.allow-origin: "*"

再次连接,发现状态变成绿色,说明连接成功

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_head插件_06

(3)安装 IK 分词器

Elasticsearch 安装插件的方式安装 IK 分词器,在 Elasticsearch 的目录下面有个叫 plugins 的,就是用来存放插件的目录,所以直接解压 IK 分词器复制过去即可

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_head插件_07

重启 Elasticsearch 之后,观察一下日志,发现多了一个加载插件

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_ik分词器_08


如果启动报错:Plugin [analysis-ik] was built for Elasticsearch version 8.2.3 but version7.6.1,只需要将 IK 插件的 plugin-descriptor.properties 配置文件的 ES 版本修改为安装版本即可

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_head插件_09

(4)安装 Kibana

安装 Kibana 不需要技巧,解压找到 bin 目录下的 kibana.bat,双击启动即可,浏览器访问:http://localhost:5601/

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_ik分词器_10

  • Kibana 设置中文,找到 kibana-7.6.1/config/kibana.yml 的,最后增加一个语言配置

i18n.locale: "zh-CN"

汉化效果如下所示

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_springboot_11

启动完成之后,可以观察一下 Head 插件的变化,是不是多了 Kibana 的信息

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_kibana_12

二、SpringBoot 搭建 ES 环境

1、SpringBoot 集成 ES

直接干货,SpringBoot 基础不好的同学,建议先学习一下 SpringBoot,下面文章内容的分享,直接是在熟练使用 SpringBoot 的前提下进行的

导入依赖到 SpringBoot,我这里使用的是 springboot 提供的

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

顺着官方文档看一下,需要先注入一个 Bean,RestHighLevelClient 是用来执行请求命令的客户端

package cn.tellsea.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;

/**
* ES 配置
*
* @author Tellsea
* @date 2022/7/28
*/
@Configurable
public class ElasticSearchConfig {

@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")
));
return client;
}
}

到这里就集成完成了,SpringBoot 的自动装配,还是一样的轻松自如,导入依赖,加个配置就 OK 了

2、概念入门思想

集群,节点,索引,类型,文档,分片,映射

elasticsearch 是面向文档,关系行数据库和 elasticsearch 客观的对比,一切都是 JSON

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_elasticsearch_13


直接转换到 Navicat 里面,一张图更好理解

【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6(官方文档解读)_kibana_14

三、Elasticsearch 官方文档 API

Java 高级 REST 客户端支持以下文档 API:单文档 API、多文档 API

  • 官方文档 7.6 API:​​https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.6/java-rest-high-supported-apis.html​​

假设我们的单元测试类,已经做了如下操作,注入可客户端 Bean(restHighLevelClient),创建了一个全局常量,也就是索引名称

@SpringBootTest
class SpringBootElasticsearchApplicationTests {

@Autowired
private RestHighLevelClient restHighLevelClient;

/**
* 索引
*/
public final static String ES_INDEX = "test_index";

}

1、索引 API

(1)创建索引

/**
* 创建索引
*/
@Test
public void createIndex() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(ES_INDEX);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
if (createIndexResponse.equals(ES_INDEX)) {
System.out.println("创建索引成功");
} else {
System.out.println("创建索引失败");
}
}

(2)索引是否存在

/**
* 索引是否存在
*/
@Test
public void existsIndex() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest(ES_INDEX);
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
if (exists) {
System.out.println("存在");
} else {
System.out.println("不存在");
}
}

(3)获取索引

/**
* 获取索引
*/
@Test
public void getIndex() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest(ES_INDEX);
GetIndexResponse getIndexResponse = restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(getIndexResponse.getAliases());
}

(4)删除索引

/**
* 删除索引
*/
@Test
public void deleteIndex() throws IOException {
DeleteIndexRequest deleteRequest = new DeleteIndexRequest(ES_INDEX);
AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(deleteRequest, RequestOptions.DEFAULT);
if (acknowledgedResponse.isAcknowledged()) {
System.out.println("删除索引成功");
} else {
System.out.println("删除索引失败");
}
}

2、文档 API

(1)添加文档

/**
* 添加文档
*/
@Test
public void addDocument() throws IOException {
User user = new User().setUserName("张三").setAge(24);
IndexRequest indexRequest = new IndexRequest(ES_INDEX);
indexRequest.source(JSON.toJSONString(user), XContentType.JSON);
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
if ("CREATED".equals(indexResponse.status())) {
System.out.println("新增文档");
} else if ("UPDATE".equals(indexResponse.status())) {
System.out.println("更新文档");
}
}

(2)文档是否存在

/**
* 文档是否存在
*/
@Test
public void existsDocument() throws IOException {
GetRequest getRequest = new GetRequest(ES_INDEX, "1");
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
if (exists) {
System.out.println("存在");
} else {
System.out.println("不存在");
}
}

(3)获取文档

/**
* 获取文档
*/
@Test
public void getDocument() throws IOException {
GetRequest getRequest = new GetRequest(ES_INDEX, "1");
GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(documentFields.getSourceAsString());
}

(4)更新文档

/**
* 更新文档
*/
@Test
public void updateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(ES_INDEX, "1");
updateRequest.timeout("1s");
User user = new User().setUserName("李四").setAge(25);
updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
if (updateResponse.status().getStatus() == 200) {
System.out.println("更新文档成功");
} else {
System.out.println("更新文档失败");
}
}

(4)删除文档

/**
* 删除文档
*/
@Test
public void deleteDocument() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(ES_INDEX, "1");
deleteRequest.timeout("1s");
DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
if (deleteResponse.status().getStatus() == 200) {
System.out.println("删除文档成功");
} else {
System.out.println("删除文档失败");
}
}

3、批量 API

(1)批量导入数据

/**
* 批量导入数据
*/
@Test
public void bulkAdd() throws IOException {
BulkRequest bulkRequest = new BulkRequest(ES_INDEX);
bulkRequest.timeout("10s");
List<User> userList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
userList.add(new User().setUserName("用户" + (i + 1)).setAge((i + 1) * 10));
}
for (int i = 0; i < userList.size(); i++) {
bulkRequest.add(new IndexRequest(ES_INDEX)
.id(String.valueOf(i + 1))
.source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()) {
System.out.println("批量导入数据成功");
} else {
System.out.println("批量导入数据失败");
}
}

(2)查询数据

/**
* 查询数据
*/
@Test
public void search() throws IOException {
SearchRequest searchRequest = new SearchRequest(ES_INDEX);

// 精准查询
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("userName.keyword", "Tellsea");
searchSourceBuilder.query(termQueryBuilder);

// 超时
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

// 分页
searchSourceBuilder.from(1);
searchSourceBuilder.size(10);

searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

// 解析结果
List<User> userList = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
userList.add(JSON.parseObject(hit.getSourceAsString(), User.class));
}

// 打印结果
userList.forEach(item -> System.out.println(item));
}

(3)查询数据-分页

/**
* 查询数据-分页
*/
@Test
public void searchPage() throws IOException {
SearchRequest searchRequest = new SearchRequest(ES_INDEX);

// 精准查询
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("userName.keyword", "Tellsea");
searchSourceBuilder.query(termQueryBuilder);

// 超时
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

// 解析结果
List<User> userList = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
userList.add(JSON.parseObject(hit.getSourceAsString(), User.class));
}

// 打印结果
userList.forEach(item -> System.out.println(item));
}

(3)查询数据-高亮

/**
* 查询数据-高亮
*/
@Test
public void searchHighlight() throws IOException {
SearchRequest searchRequest = new SearchRequest(ES_INDEX);

// 精准查询
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("userName.keyword", "Tellsea");
searchSourceBuilder.query(termQueryBuilder);

// 超时
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

// 分页
searchSourceBuilder.from(1);
searchSourceBuilder.size(10);

// 高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("userName");
highlightBuilder.preTags("<span style='color: red;'>");
highlightBuilder.postTags("</span>");
searchSourceBuilder.highlighter(highlightBuilder);

searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

// 解析结果
List<User> userList = new ArrayList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
// 如果没有高亮,直接解析JSON放到list即可
// userList.add(JSON.parseObject(hit.getSourceAsString(), User.class));

// 解析高亮
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField userName = highlightFields.get("userName");
// 原来的结果
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
if (userName != null) {
Text[] fragments = userName.fragments();
String n_userName = "";
for (Text text : fragments) {
n_userName += text;
}
sourceAsMap.put("userName", n_userName);
}
userList.add(JSON.parseObject(JSON.toJSONString(sourceAsMap), User.class));
}

// 打印结果
userList.forEach(item -> System.out.println(item));
}

到此 ES 的基本操作,已经学习完了!后续有空会整理更多高级的操作等


举报

相关推荐

0 条评论