@
-
1、相关文档、链接
-
2、软件安装
-
(1)安装 Elasticsearch
-
(2)安装 Head
-
(3)安装 IK 分词器
-
(4)安装 Kibana
-
1、SpringBoot 集成 ES
-
2、概念入门思想
-
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 系列文章中说明。下载完所有软件之后,如下所示
(1)安装 Elasticsearch
Elasticsearch 安装很简单,直接解压,找到 bin/elasticsearch.bat 双击启动就可以了
日志中有这么一句话
[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,浏览器直接访问这个地址即可,如下所示
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 http://localhost:9100/
这将启动一个在端口 9100 上运行的本地网络服务器,服务于 elasticsearch-head
点击上面的连接,发现连接不上,打开 F12 控制台,发现疯狂报错跨域找到 elasticsearch-7.6.1/config/elasticsearch.yml 配置文件,在末尾添加跨域支持,然后重启 Elasticsearch
# 支持跨域访问
http.cors.enabled: true
http.cors.allow-origin: "*"
再次连接,发现状态变成绿色,说明连接成功
(3)安装 IK 分词器
Elasticsearch 安装插件的方式安装 IK 分词器,在 Elasticsearch 的目录下面有个叫 plugins 的,就是用来存放插件的目录,所以直接解压 IK 分词器复制过去即可
重启 Elasticsearch 之后,观察一下日志,发现多了一个加载插件如果启动报错:Plugin [analysis-ik] was built for Elasticsearch version 8.2.3 but version7.6.1,只需要将 IK 插件的 plugin-descriptor.properties 配置文件的 ES 版本修改为安装版本即可
(4)安装 Kibana
安装 Kibana 不需要技巧,解压找到 bin 目录下的 kibana.bat,双击启动即可,浏览器访问:http://localhost:5601/
-
Kibana 设置中文,找到 kibana-7.6.1/config/kibana.yml 的,最后增加一个语言配置
i18n.locale: "zh-CN"
汉化效果如下所示
启动完成之后,可以观察一下 Head 插件的变化,是不是多了 Kibana 的信息
二、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
直接转换到 Navicat 里面,一张图更好理解
三、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 的基本操作,已经学习完了!后续有空会整理更多高级的操作
原文始发于微信公众号(花海里):【SpringBoot学习】44、SpringBoot 集成 Elasticsearch-7.6 实战
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/69553.html