目录

1、es - 概述、功能、场景

2、es-核心概念:索引、类型、文档、映射

3、 es - 详解倒排索引

4、索引操作 - 创建、查看、删除

5、检索es基本信息

6、document - 增删改查文档

1)新增保存

2)查看

3)更新文档

4)删除文档或索引

5)ES的批量操作-bulk


1、es - 概述、功能、场景

        Elaticsearch,简称为es,是一个基于Lucene的搜索服务器。它提供了一个分布式多用户功能的全文搜索引擎,基于Restful web接口。ElasticSearch是用java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎;

功能:

  • 分布式的搜索引擎(搜索:百度、谷歌,站内搜索):分布式:Elasticsearch自动将海量数据分散到多台服务器上去存储和检索
  • 全文检索:提供模糊搜索等自动度很高的查询方式,并进行相关性排名,高亮等功能
  • 数据分析引擎(分组聚合):电商网站,最近一周笔记本电脑这种商品销量排名top10的商家有哪些?新闻网站,最近1个月访问量排名top3的新闻板块是哪些
  • 对海量数据进行近实时的处理:因为是分布式架构,Elasticsearch可以采用大量的服务器去存储和检索数据,自然而然就可以实现海量数据的处理
  • 近实时:Elasticsearch可以实现秒级别的数据搜索和分析

企业使用场景:

  • 搜索类场景:比如说电商网站、招聘网站、新闻资讯类网站、各种app内的搜索;
  • 日志分析类场景:经典的ELK组合(Elasticsearch/Logstash/Kibana),可以完成日志收集,日志存储,日志分析查询界面基本功能,目前该方案的实现很普及,大部分企业日志分析系统使用了该方案;
  • 数据预警平台:例如电商价格预警,在支持的电商平台设置价格预警,当优惠的价格低于某个值时,触发通知消息,通知用户购买;
  • 数据分析场景:数据分析常见的比如分析电商平台销售量top 10的品牌,分析博客系统、头条网站top 10关注度、评论数、访问量的内容等;

2、es-核心概念:索引、类型、文档、映射

1)index索引:
        类似的数据放在一个索引,非类似的数据放不同索引, 一个索引也可以理解成一个关系型数据库;

2)Type类型:(es7会逐渐删除type,官方说在8.x版本会彻底移除type)

  1. ES 5.x中一个index可以有多种type
  2. ES 6.x中一个index只能有一种type
  3. ES 7.x以后要逐渐移除type这个概念

3)Document文档:
        保存在某个index下,某种type的一个数据document,文档是json格式的,document就像是mysql中的某个table里面的内容,每一行对应的列叫属性;

es父子文档 aggs es的文档_es父子文档 aggs

3、 es - 详解倒排索引

1)简单介绍

        下图是ElasticSearch的索引结构,下边黑色部分是物理结构,上边黄色部分是逻辑结构,逻辑结构也是为了更好的去描述ElasticSearch的工作原理及去使用物理结构中的索引文件

es父子文档 aggs es的文档_搜索_02

 2)逻辑结构部分是一个倒排索引表

  1. 将要搜索的文档内容分词,所有不重复的词组成分词列表
  2. 将搜索的文档最终以Document方式存储起来
  3. 每个词和docment都有关联

es父子文档 aggs es的文档_数据_03

 3)倒序为什么查询快(通过词找文章)

(1)会有一个倒排索引表,首先对红海行动进行分词,分词后的数据插入到倒排索引表中。
保存的记录(红海行动、探索红海行动、红海特别行动、红海记录片、特工红海特别探索)
(2) 将内容分词就记录到索引中:

es父子文档 aggs es的文档_数据_04

 (3)检索红海特工行动?查出后计算相关性得分:3号(红海特别行动)记录命中了2次,且3号本身才有3个单词,2/3,所以3号最匹配。5号(特工红海特别探索)四个命中了2个;

4、索引操作 - 创建、查看、删除

1)创建索引库:PUT /索引名称

es父子文档 aggs es的文档_开发语言_05

2)判断索引是否存在:HEAD /索引名称

# 200表示索引在es中存在
200 - OK
# 404表示索引在es中不存在
404 - Not Found

3)查看单个索引:GET /索引名称

4)批量查看索引:GET /索引名称1,索引名称2,索引名称3…

5)查看所有索引

  1. GET _all
  2. GET /_cat/indices?v

6)打开和关闭索引(关闭后的索引不能搜索数据)

  1. POST /索引名称/_open
  2. POST /索引名称/_close

7)删除索引使用DELETE请求:DELETE /索引名称1,索引名称2,索引名称3…

5、检索es基本信息

1)GET /_cat/nodes:查看所有节点

127.0.0.1 16 94 3 0.01 0.03 0.05 dilm * f35e9eb81345

2)GET /_cat/health:查看es健康状况

//注:green表示健康值正常
1647766085 08:48:05 elasticsearch yellow 1 1 5 5 0 0 2 0 - 71.4%

3)GET /_cat/master:查看主节点

Kcb7reXVSEiIQL-gxvgdXg 127.0.0.1 127.0.0.1 f35e9eb81345

4)GET /_cat/indices:查看所有索引,等价于mysql数据库的show databases;

green  open .kibana_task_manager_1   DhtDmKrsRDOUHPJm1EFVqQ 1 0 2 3 40.8kb 40.8kb
green  open .apm-agent-configuration vxzRbo9sQ1SvMtGkx6aAHQ 1 0 0 0   230b   230b
green  open .kibana_1                rdJ5pejQSKWjKxRtx-EIkQ 1 0 5 1 18.2kb 18.2kb
这3个索引是kibana创建的

6、document - 增删改查文档

1)新增保存

保存一个数据,保存在哪个索引的哪个类型下(哪张数据库哪张表下),保存时用唯一标识指定

  • POST新增:

-如果不指定id,会自动生成id,指定id就会修改这个数据,并新增版本号

-可以不指定id,不指定id时永远为创建

-指定不存在的id为创建

-指定存在的id为更新(带了_update操作的),而版本号(_seq_no)会根据内容变没变而觉得版本号递增与否

  • PUT新增

-PUT必须指定id;由于PUT需要指定id,我们一般用来做修改操作,不指定id会报错
-必须指定id、版本号总会增加
-put和java里map.put一样必须指定key-value。而post相当于mysql insert

# 在customer索引下的external类型下保存1号数据
PUT customer/external/1
{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}

es父子文档 aggs es的文档_搜索_06

 seq_no和version的区别:

  • 每个文档的版本号"_version" 起始值都为1,每次对当前文档成功操作后都加1
  • 而序列号"_seq_no"则可以看做是索引的信息 在第一次为索引插入数据时为0,每对索引内数据操作成功一次sqlNO加1,并且文档会记录是第几次操作使它成为现在的情况的

2)查看

GET /customer/external/1
{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 10,
    "_seq_no": 18,//并发控制字段,每次更新都会+1,用来做乐观锁
    "_primary_term": 6,//同上,主分片重新分配,如重启,就会变化
    "found": true,
    "_source": {
        "name": "John Doe"
    }
}

        乐观锁用法:通过“if_seq_no=1&if_primary_term=1”,当序列号匹配的时候,才进行修改,否则不修改;实例:将id=1的数据更新为name=1,然后再次更新为name=2,起始1_seq_no=18,_primary_term=6
(1).将name更新为1:PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=18&if_primary_term=6

es父子文档 aggs es的文档_es父子文档 aggs_07

 (2).将name更新为2,更新过程中使用seq_no=18:PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=18&if_primary_term=6,结果为:(出现更新错误)

es父子文档 aggs es的文档_数据_08

 (3). 查询新的数据 GET http://192.168.56.10:9200/customer/external/1

es父子文档 aggs es的文档_数据_09

 (4). 再次更新,更新成功:PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=19&if_primary_term=1

3)更新文档

        携带_update参数会去检查元数据,如果更新的数据和元数据对比没有变化,则不会叠加版本;

# 对比原来的数据,与原来的数据一样就什么都不做,version、seq_no都不变
POST customer/external/1/_update
{
  "doc":{
      "name":"111"
  }
}

//不会检查元数据,它的版本号都会更新,不断的叠加版本
POST customer/external/1
{
	"name":"222"
}

PUT customer/external/1
{
	"name":"222"
}

//更新同时增加属性,PUT和不带POST不带_update都可以
POST customer/external/1/_update
{
	"doc":{"name":"Jane","age":26}
}

4)删除文档或索引

elasticsearch并没有提供删除类型的操作,只提供了删除索引和文档的操作。

1、删除customer/external id=1的数据:

//DELETE customer/external/1
实例:删除id=1的数据,删除后继续查询
DELETE http://192.168.56.10:9200/customer/external/1
{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 14,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 22,
    "_primary_term": 6
}
再次执行DELETE http://192.168.56.10:9200/customer/external/1
{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 15,
    "result": "not_found",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 23,
    "_primary_term": 6
}
GET http://192.168.56.10:9200/customer/external/1
{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "found": false
}

 2、删除customer索引:

删除前,所有的索引http://192.168.56.10:9200/_cat/indices
green  open .kibana_task_manager_1   DhtDmKrsRDOUHPJm1EFVqQ 1 0 2 0 31.3kb 31.3kb
green  open .apm-agent-configuration vxzRbo9sQ1SvMtGkx6aAHQ 1 0 0 0   283b   283b
green  open .kibana_1                rdJ5pejQSKWjKxRtx-EIkQ 1 0 8 3 28.8kb 28.8kb
yellow open customer                 mG9XiCQISPmfBAmL1BPqIw 1 1 9 1  8.6kb  8.6kb
删除“ customer ”索引
DELTE http://192.168.56.10:9200/customer
响应
{
    "acknowledged": true
}
删除后,所有的索引http://192.168.56.10:9200/_cat/indices
green open .kibana_task_manager_1   DhtDmKrsRDOUHPJm1EFVqQ 1 0 2 0 31.3kb 31.3kb
green open .apm-agent-configuration vxzRbo9sQ1SvMtGkx6aAHQ 1 0 0 0   283b   283b
green open .kibana_1                rdJ5pejQSKWjKxRtx-EIkQ 1 0 8 3 28.8kb 28.8kb

5)ES的批量操作-bulk

        这里的批量操作,当发生某一条执行发生失败时,其他的数据仍然能够接着执行,也就是说彼此之间是独立的

1、执行多条数据:

POST /customer/external/_bulk
{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"John Doe"}
#! Deprecation: [types removal] Specifying types in bulk requests is deprecated.
{
  "took" : 318,  花费了多少ms
  "errors" : false, 没有发生任何错误
  "items" : [ 每个数据的结果
    {
      "index" : { 保存
        "_index" : "customer", 索引
        "_type" : "external", 类型
        "_id" : "1", 文档
        "_version" : 1, 版本
        "result" : "created", 创建
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 201 新建完成
      }
    },
    {
      "index" : { 第二条记录
        "_index" : "customer",
        "_type" : "external",
        "_id" : "2",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}

2、对于整个索引执行批量操作:

POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"my first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"my second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123"}}
{"doc":{"title":"my updated blog post"}}
运行结果:
#! Deprecation: [types removal] Specifying types in bulk requests is deprecated.
{
  "took" : 304,
  "errors" : false,
  "items" : [
    {
      "delete" : { 删除
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "_version" : 1,
        "result" : "not_found", 没有该记录
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 0,
        "_primary_term" : 1,
        "status" : 404 没有该
      }
    },
    {
      "create" : {  创建
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "_version" : 2,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "index" : {  保存
        "_index" : "website",
        "_type" : "blog",
        "_id" : "5sKNvncBKdY1wAQmeQNo",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 2,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "update" : { 更新
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "_version" : 3,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 3,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}