ElasticSearch入门详解(结合Kibana)
前言
ElasticSearch是基于java的开源分布式搜索引擎,由于其强大的检索性能和较好的封装性(对lunece),给用户提供了简单易上手的API操作,也成为当前各大企业和大厂用于搜索引擎的工具。本文将对ElasticSearch的使用和入门进行详细的讲解,并结合Kibana进行部分案例的演示,希望可以让各位读者有所收获。想要获取更多有关ElasticStack其他成员的使用,可以关注本文集的其他文章。
一、应用安装
(一)安装ElasticSearch
1. 去官网下载解压包:https://www.elastic.co/downloads/elasticsearch
2. 解压和使用
将压缩包解压到指定路径后,进入bin目录执行
elasticsearch.bat
即可启动注意:
-
ElasticSearch
依赖于jdk环境,要求本地的jdk版本最低为jdk1.8! -
ElasticSearch
官网可能进不去,有需要的话可以从文章中获取百度网盘链接
(二)安装Kibana
- 进入官网下载:https://www.elastic.co/cn/kibana
- 解压和使用
将压缩包解压后,进入bin目录执行kibana.bat
即可
如果对应的elasticsearch服务不在默认的端口和ip,则需要进入到config目录中,在kibana.yml
文件中添加对应的配置
elasticsearch.hosts: ["http://localhost:9200"]
# 要修改启动kibana的端口的话,可以修改下面的配置
server.port: 5601
(三)安装elasticsearch-head
插件
elasticsearch-head将是一款专门针对于elasticsearch的客户端工具,我们可以通过这个可视化工具来便捷地查看当前es集群的各种信息。
- 下载地址:https://github.com/mobz/elasticsearch-head
- 解压和安装
elasticsearch-head依赖于node.js,我们需要提前准备好相关的环境,解压后进入主目录执行下面的命令
# 下载对应前端依赖 (如果太慢的话可以换成淘宝镜像下载,具体自行百度)
npm install
# 启动
npm run start
由于跨域问题的存在,使用elasticsearch-head
前我们需要先进入前面安装elasticsearch
的目录中配置允许跨域
添加入下配置:
http.cors.enabled: true
http.cors.allow-origin: "*"
二、ES的核心概念
(一)数据类型
elasticsearch
是面向文档关系行数据库,为了便于理解其相关的核心概念,我们可以将其与传统的关系型数据库进行参考,以便快速的理解核心概念的含义。
名称 | 含义 |
---|---|
数据库(database) | 索引(indices) |
表(tables) | types (慢慢被弃用) |
行(rows) | documents |
字段(columns) | fields |
(二)检索方式——倒排索引
以下图为例,左侧是文章id和每篇文章对应的标签。当使用倒排索引的时候,会将标签分为两类,这样的话当我们想搜索和python
相关的博客的时候,就无需搜索全部文章,而只需要从索引列表中检索即可。大大提高了检索效率。(倒排索引的核心在于分词)
三、实操——通过REST风格进行ES的CRUD操作
method | url地址 | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id | 通过文档id查询文档 |
POST | localhost:9200/索引名称/类型名称/_search | 查询所有的数据 |
启动ES
和Kibana
服务,进入Kibana
左侧菜单栏的Dev Tool
(一)PUT 命令
1、使用es默认提供的数据类型
PUT /index_test1/_doc/1
{
"name": "小明",
"age": 10
}
响应结果
{
"_index" : "index_test1",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
我们可以看到,通过这种方式新建的索引数据,es会默认给上对应的字段类型。如果有需要指定类型的话,需要我们进行自定义。
2、自定义索引表字段类型
2.1、字段的类型
字符串类型: text、keyword
数值类型: long、integer、short、byte、double、float、half、float、scaled、
日期类型:date
布尔值类型: boolean
二进制类型: binary
2.2、自定义索引字段类型
PUT /index_test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
}
}
}
}
我们可以看到自定义字段后,再次查询得到的结果就是我们定义好的类型了。
2.3、扩展命令
GET _cat/health 获取es健康值
GET _cat/indices 获取es的所有索引
2.4、索引数据修改
- 使用
PUT
命令
PUT /index_test1/_doc/1
{
"name": "小蓝"
}
响应结果如下:
{
"_index" : "index_test1", // 索引名称
"_type" : "_doc", // 索引类型
"_id" : "1", // 数据id
"_version" : 2, // 版本,每修改一次数据版本+1
"result" : "updated", // 状态:已更新
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
我们查看数据发现,源数据确认已经修改成功,但是age
字段的值却变为了空。
这是因为
elasticSearch
使用PUT
命令进行更新的时候,对于没有赋值的字段会一律修改为空。所以一般来说,我们基本上是使用POST方法来进行更新的
POST /index_test1/_doc/1/_update
{
"doc": {
"name": "小蓝"
}
}
(二)DELETE
DELETE一般用于索引的删除,使用方式也十分简单
DELETE /index_test1
(三)GET
我们可以利用GET来查看索引和文档,查询的请求头格式如下:
GET /索引/类型/文档
对于查询体,也就是查询的具体条件,es支持两种查询方式。常规的REST URI方式和REST 请求体
方式
-
URI方式
对于REST请求体方式,则在下一节进行讲解
四、关于ES多条件查询详解
1. 模糊查询(match)
GET /index_test1/_doc/_search
{
"query": {
"match": {
"name": "小明"
}
}
}
2. 排序(sort)
GET /index_test1/_doc/_search
{
"query": {
"match": {
"name": "小明"
}
},
"sort": [
{
"age": "desc"
}
]
}
3. 字段选择(source)
GET /index_test1/_doc/_search
{
"query": {
"match": {
"name": "小明"
}
},
"_source": ["name"]
}
4. 限制结果记录条数(from 、size)
GET /index_test1/_doc/_search
{
"query": {
"match": {
"name": "小明"
}
},
"from": 1,
"size": 1
}
5. 条件查询(可以写多个查询条件,并进行与或非逻辑判断)
GET /index_test1/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "小明"
}
},
{
"match": {
"age": 11
}
}
]
}
}
}
6. 过滤器(filter)
- gt 大于
- gte 大于或等于
- lt 小于
- lte 小于或等于
GET /index_test1/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"name": "明"
}
}
],
"filter": {
"range": {
"age": {
"gte": 15,
"lte": 26
}
}
}
}
}
}
7. 精准查询(term)
term 查询是直接通过倒排索引指定的词条进行精确查找的,因为倒排索引大大缩小了检索的范围,这也使得使用term
关键字的搜索效率很高。
GET /index_test1/_search
{
"query": {
"term": {
"name": "明"
}
}
}
8. 高亮查询
GET /index_test1/_search
{
"query": {
"match": {
"name": "小明"
}
},
"highlight": {
"pre_tags": "<p class='a' >",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
五、在项目(JAVA)中使用ES客户端进行操作
(一)新建项目并导入项目依赖
创建一个springboot的项目 同时勾选上springboot-web的包以及Nosql的elasticsearch的包
<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>
注意,引入后要注意ElasticSearch
的客户端的版本是否和本地的es版本一致
如果不一致的话,就手动配置
<properties>
<!-- 这里的话,要和自己本地的es版本保持一致 -->
<elasticsearch.version>7.6.1</elasticsearch.version>
</properties>
(二)注入RestHighLevelClient 客户端
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
return restHighLevelClient;
}
}
(三)使用客户端操作索引数据
1. 创建索引
// 测试创建索引
@Test
void createESIndext() throws IOException {
// 创建索引请求
CreateIndexRequest request = new CreateIndexRequest("xiaoming_index");
// 通过高级客户端调用相关索引客户端,并执行请求
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
// 输出请求
System.out.println(createIndexResponse);
}
2. 查询索引是否存在
// 测试查询索引
@Test
void searchESIndext() throws IOException {
// 创建索引请求
GetIndexRequest request = new GetIndexRequest("xiaoming_index");
// 通过高级客户端调用相关索引客户端,并执行请求
boolean isExist = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
// 输出请求
System.out.println("xiaoming_index is Exist : " + isExist);
}
3.删除索引
// 测试删除索引
@Test
void deleteESIndext() throws IOException {
// 创建索引请求
DeleteIndexRequest request = new DeleteIndexRequest("xiaoming_index");
// 通过高级客户端调用相关索引客户端,并执行请求
AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
// 输出请求
System.out.println(response.isAcknowledged());
}
4. 创建索引文档
// 测试创建文档
@Test
void createESDocument() throws IOException {
// 创建对象
Student stu = new Student("小明",18);
// 创建索引相关请求
IndexRequest request = new IndexRequest("xiaoming_index");
// 配置请求相关参数
request.id("1");
request.timeout("1s");
request.source(JSON.toJSONString(stu), XContentType.JSON);
// 通过客户端执行请求
IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
// 输出请求
System.out.println(response.status());
}
5. 判断文档是否存在
// 判断文档是否存在
@Test
void searchESDocument() throws IOException {
// 创建索引相关请求
GetRequest request = new GetRequest("xiaoming_index", "1");
// 配置不显示索引上下文
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
// 获取文档信息
boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
// 输出请求
System.out.println(exists);
}
6. 获取文档内容
@Test
void searchESDocumentDetails() throws IOException {
// 创建索引相关请求
GetRequest request = new GetRequest("xiaoming_index", "1");
// 获取文档信息
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
// 输出具体数据
System.out.println(response.getSourceAsString());
// 输出全部结果
System.out.println(response);
}
7. 更新文档内容
@Test
void updateESDocumentDetails() throws IOException {
// 创建索引相关请求
UpdateRequest request = new UpdateRequest("xiaoming_index", "1");
// 插入更新的文档内容
Student student = new Student("大明", 14);
request.doc(JSON.toJSONString(student),XContentType.JSON);
// 更新文档信息
UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
// 输出具体数据
System.out.println(response.status());
// 输出全部结果
System.out.println(response);
}
8. 删除文档记录
// 删除文档记录
@Test
void deleteESDocumentDetails() throws IOException {
// 创建索引相关请求
DeleteRequest request = new DeleteRequest("xiaoming_index", "1");
// 更新文档信息
DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
// 输出具体数据
System.out.println(response.status());
// 输出全部结果
System.out.println(response);
}
9. 对文档记录进行批量操作
@Test
void bulkESDocument() throws IOException {
// 创建批量操作索引请求
BulkRequest bulkRequest = new BulkRequest();
// 初始化数据
ArrayList list = new ArrayList();
list.add(new Student("小红", 15));
list.add(new Student("小蓝", 15));
list.add(new Student("小黑", 63));
list.add(new Student("小青", 14));
// 创建具体的插入数据请求,并加入到批量请求中
for(int i = 0 ;i<list.size() ; i++){
bulkRequest.add(new IndexRequest("xiaoming_index")
.id(String.valueOf(i+1))
.source(JSON.toJSONString(list.get(i)),XContentType.JSON));
}
// 执行批量操作
BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
// 输出具体数据
System.out.println(response.status());
// 输出全部结果
System.out.println(response);
}
10.根据条件查询文档信息
@Test
void searchDocumentByCondition() throws IOException {
// 创建请求对象
SearchRequest searchRequest = new SearchRequest("xiaoming_index");
// 创建查询条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("name", "蓝"));
searchRequest.source(searchSourceBuilder);
// 执行查询
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(response.getHits()));
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
参考学习视频:
【狂神说Java】ElasticSearch7.6.x最新完整教程通俗易懂
https://www.bilibili.com/video/BV17a4y1x7zq(一个蛮好的up主,大家可以多关注关注)