ElasticSearch入门详解(结合Kibana)

前言

ElasticSearch是基于java的开源分布式搜索引擎,由于其强大的检索性能和较好的封装性(对lunece),给用户提供了简单易上手的API操作,也成为当前各大企业和大厂用于搜索引擎的工具。本文将对ElasticSearch的使用和入门进行详细的讲解,并结合Kibana进行部分案例的演示,希望可以让各位读者有所收获。想要获取更多有关ElasticStack其他成员的使用,可以关注本文集的其他文章。

一、应用安装

(一)安装ElasticSearch

1. 去官网下载解压包:https://www.elastic.co/downloads/elasticsearch

image.png

2. 解压和使用
将压缩包解压到指定路径后,进入bin目录执行elasticsearch.bat即可启动
image.png

注意:

  • ElasticSearch依赖于jdk环境,要求本地的jdk版本最低为jdk1.8!
  • ElasticSearch官网可能进不去,有需要的话可以从文章中获取百度网盘链接

(二)安装Kibana

  1. 进入官网下载:https://www.elastic.co/cn/kibana
  2. 解压和使用
    将压缩包解压后,进入bin目录执行kibana.bat即可
    image.png

    如果对应的elasticsearch服务不在默认的端口和ip,则需要进入到config目录中,在kibana.yml文件中添加对应的配置
elasticsearch.hosts: ["http://localhost:9200"]
# 要修改启动kibana的端口的话,可以修改下面的配置
server.port: 5601

(三)安装elasticsearch-head插件

elasticsearch-head将是一款专门针对于elasticsearch的客户端工具,我们可以通过这个可视化工具来便捷地查看当前es集群的各种信息。

  1. 下载地址:https://github.com/mobz/elasticsearch-head
  2. 解压和安装
    elasticsearch-head依赖于node.js,我们需要提前准备好相关的环境,解压后进入主目录执行下面的命令
# 下载对应前端依赖 (如果太慢的话可以换成淘宝镜像下载,具体自行百度)
npm install 
# 启动
npm run start

由于跨域问题的存在,使用elasticsearch-head前我们需要先进入前面安装elasticsearch的目录中配置允许跨域

es的配置文件

添加入下配置:

http.cors.enabled: true
http.cors.allow-origin: "*"

二、ES的核心概念

(一)数据类型

elasticsearch是面向文档关系行数据库,为了便于理解其相关的核心概念,我们可以将其与传统的关系型数据库进行参考,以便快速的理解核心概念的含义。

名称 含义
数据库(database) 索引(indices)
表(tables) types (慢慢被弃用)
行(rows) documents
字段(columns) fields

(二)检索方式——倒排索引

以下图为例,左侧是文章id和每篇文章对应的标签。当使用倒排索引的时候,会将标签分为两类,这样的话当我们想搜索和python相关的博客的时候,就无需搜索全部文章,而只需要从索引列表中检索即可。大大提高了检索效率。(倒排索引的核心在于分词)

image.png

三、实操——通过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 查询所有的数据

启动ESKibana服务,进入Kibana左侧菜单栏的Dev Tool

kibana页面

(一)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"
      }
    }
  }
}

我们可以看到自定义字段后,再次查询得到的结果就是我们定义好的类型了。


image.png
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字段的值却变为了空。

image.png

这是因为elasticSearch使用PUT命令进行更新的时候,对于没有赋值的字段会一律修改为空。所以一般来说,我们基本上是使用POST方法来进行更新的

POST /index_test1/_doc/1/_update
{
  "doc": {
    "name": "小蓝"
  }
}
使用post更新,原来其他字段的值还在

(二)DELETE

DELETE一般用于索引的删除,使用方式也十分简单

DELETE /index_test1

(三)GET

我们可以利用GET来查看索引和文档,查询的请求头格式如下:

GET /索引/类型/文档

对于查询体,也就是查询的具体条件,es支持两种查询方式。常规的REST URI方式和REST 请求体方式

  • URI方式


    image.png

    对于REST请求体方式,则在下一节进行讲解

四、关于ES多条件查询详解

1. 模糊查询(match)
GET /index_test1/_doc/_search
{
  "query": {
    "match": {
      "name": "小明"
    }
  }
}
image.png
2. 排序(sort)
GET /index_test1/_doc/_search
{
  "query": {
    "match": {
      "name": "小明"
    }
  },
  "sort": [
    {
      "age": "desc"
    }
  ]
}
image.png
3. 字段选择(source)
GET /index_test1/_doc/_search
{
  "query": {
    "match": {
      "name": "小明"
    }
  },
  "_source": ["name"]
}
image.png
4. 限制结果记录条数(from 、size)
GET /index_test1/_doc/_search
{
  "query": {
    "match": {
      "name": "小明"
    }
  },
  "from": 1, 
  "size": 1 
}
image.png
5. 条件查询(可以写多个查询条件,并进行与或非逻辑判断)
GET /index_test1/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "小明"
          }
        },
        {
          "match": {
            "age": 11
          }
        }
      ]
    }
  }
}
must结果集响应
should结果集响应
must_not
6. 过滤器(filter)
- gt  大于
- gte 大于或等于
- lt  小于
- lte 小于或等于
GET /index_test1/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "name": "明"
          }
        }
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 15,
            "lte": 26
          }
        }
      }
    }
  }
}
filter的使用
7. 精准查询(term)

term 查询是直接通过倒排索引指定的词条进行精确查找的,因为倒排索引大大缩小了检索的范围,这也使得使用term关键字的搜索效率很高。

GET /index_test1/_search
{
  "query": {
    "term": {
      "name": "明"
    }
  }
}
term关键字查询
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版本一致

查看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主,大家可以多关注关注)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容