03.Elasticsearch应用(三)

Elasticsearch应用(三)

1.核心概念介绍

在这里插入图片描述
注意:类型(Type)
6.0之前的版本有Type概念,type相当于关系型数据库的表,ES官方将在ES9版本中彻底删除Type。7里面Type为ES默认的类型_doc

2.Cat API

介绍

ES提供了相关的Cat API用来检查ES的各种信息

API

/_cat/allocation #查看单节点的shard分配整体情况
/_cat/shards #查看各shard的详细情况
/_cat/shards/{index} #查看指定分片的详细情况
/_cat/master #查看master节点信息
/_cat/nodes #查看所有节点信息
/_cat/indices #查看集群中所有index的详细信息
/_cat/indices/{index} #查看集群中指定index的详细信息
/_cat/segments #查看各index的segment详细信息,包括segment名, 所属shard, 内存
(磁盘)占用大小, 是否刷盘
/_cat/segments/{index}#查看指定index的segment详细信息
/_cat/count #查看当前集群的doc数量
/_cat/count/{index} #查看指定索引的doc数量
/_cat/recovery #查看集群内每个shard的recovery过程.调整replica。
/_cat/recovery/{index}#查看指定索引shard的recovery过程
/_cat/health #查看集群当前状态:红、黄、绿
/_cat/pending_tasks #查看当前集群的pending task
/_cat/aliases #查看集群中所有alias信息,路由配置等
/_cat/aliases/{alias} #查看指定索引的alias信息
/_cat/thread_pool #查看集群各节点内部不同类型的threadpool的统计信息,
/_cat/plugins #查看集群各个节点上的plugin信息
/_cat/fielddata #查看当前集群各个节点的fielddata内存使用情况
/_cat/fielddata/{fields} #查看指定field的内存使用情况,里面传field属性对应的
值
/_cat/nodeattrs #查看单节点的自定义属性
/_cat/repositories #输出集群中注册快照存储库
/_cat/templates #输出当前正在存在的模板信息

3.索引基础

介绍

索引是文档的容器,是一类文档的结合

索引名命名规则
  • 仅小写
  • 不能包括,/,*,?,",<,>,|,``(空格字符), ,,#
  • 7.0之前的索引可能包含冒号(:),但已弃用,并且在7.0+中不支持
  • 不能以这些开始 -,_,+
  • 不能为.或…
  • 不能超过255个字节(请注意它是字节,因此多字节字符将更快地计入255个限制)
  • 不建议使用以.开头的名称,但隐藏索引和由插件管理的内部索引除外

基础API

增加API

您可以使用create index API将新索引添加到Elasticsearch集群。创建索引时,可以指定以下内容:

  1. 索引设置
  2. 索引中字段的映射
  3. 索引别名
# 创建索引
PUT /es_db

# 创建索引时可以设置分片数和副本数
PUT /es_db
{
	"settings" : {
		"number_of_shards" : 3,
		"number_of_replicas" : 2
	}
}
查询API
# 查询索引
GET /es_db

# es_db是否存在
# 注意:该参数不能区分索引名和别名,如果别名存才则返回200
HEAD /es_db

# 检索集群中所有索引的信息
GET /_all
删除API
  • 您不能使用别名删除索引
  • 要删除所有索引,请使用_all或*
  • 要禁止使用_all或通配符表达式删除索引,请将action.destructive_requires_name群集设置更改为true
delete /es_db
关于索引修改

索引是不允许修改的,因为索引创建完成后,它的数据结构也就是Mapping都已经定义好了,ES会基于这些Mapping来创建倒排索引,如果修改一个字段会导致原有的倒排索引整个失效,所以ES是禁止修改索引的,虽然ES不允许修改原有的字段但是允许添加新的,语法如下:

PUT /[索引名]/_mapping
{
    "properties":{
        "新字段名":{
            "type":"integer"
        }
    }
}

4.文档基础

介绍

文档就是一个JSON数据,每个文档都有一个Unique ID,可以自己指定ID或者通过Elasticsearch自动生成

JSON文档,格式灵活,不需要预先定义格式,字段的类型可以指定或者通过Elasticsearch自动推算,支持数组/支持嵌套

文档元数据

  • _index:文档所属的索引名
  • _type:文档所属的类型名
  • _id:文档唯—ld
  • _source: 文档的原始Json数据
  • _version: 文档的版本号,修改删除操作_version都会自增1
  • _seq_no: 和_version一样,一旦数据发生更改,数据也一直是累计的。Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no
  • _primary_term: _primary_term主要是用来恢复数据时处理当多个文档的_seq_no一样时的冲突,避免Primary Shard上的写入被覆盖。每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1

文档删除和修改原理说明

  1. Elasticsearch执行删除操作时,ES先标记文档为deleted状态,而不是直接物理删除。当ES存储空间不足或工作空闲时,才会执行物理删除操作
  2. Elasticsearch执行修改操作时,ES不会真的修改Document中的数据,而是标记ES中原有的文档为deleted状态,再创建一个新的文档来存储数据

基础API

增加API
# 如果指定的索引不存在会自动创建

# 添加文档并指定id,PUT请求id为必填,使用_doc创建文档如果指定id文档已存在会覆盖
PUT /[index]/_doc/[_id]
{
    请求体
}

# 添加文档不指定id,使用POST请求会自动生成id,使用_doc创建文档如果指定id文档已存在会覆盖
POST /[index]/_doc/
{
    请求体
}

# 添加文档并指定id,使用_create创建文档必须保证文档id不重复否则报错
PUT /[index]/_create/[_id]
{
    请求体
}

# 添加文档并指定id,使用_create创建文档必须保证文档id不重复否则报错
POST /[index]/_create/[_id]
{
    请求体
}
删除API
# 删除指点id的文档
DELETE /[index]/_doc/[_id]

# 根据查询API进行删除
POST /[index]/_delete_by_query
{
  "query": { 
    "match": {
      "message": "some message"
    }
  }
}
修改API
# 覆盖式修改文档,会覆盖原本id的文档
PUT /[index]/_doc/[_id]
{
    请求体
}

# 局部修改文档,更新部分文档或覆盖式更新
POST /[index]/_update/[_id]
{
    请求体
}

# 批量更新符合某个查询条件的文档
POST /es_db/_update_by_query
{
  "query": {
    "match": {
      "_id": 1
    }
  },
  "script": {
    "source": "ctx._source.age = 30"
  }
}

# 脚本更新
# es可以内置脚本执行复杂操作。例如painless脚本
# 注意:groovy脚本在es6以后就不支持了。原因是耗内存,不安全远程注入漏洞
post /[索引名]/_doc/[文档id]/_update
{
    "script":"ctx._source.字段+=1"
}
查询文档
# 要搜索的索引名称的逗号分隔列表或使用_all搜索所有索引

# 查询指定id的文档,当然这是最简单的方式,后面会详解整个文档查询
GET /es_db/_doc/1

并发场景下修改文档

_seq_no和_primary_term是对_version的优化,7.X版本的ES默认使用这种方式控制版本,所以当在高并发环境下使用乐观锁机制修改文档时,要带上当前文档的_seq_no和_primary_term进行更新

POST /es_db/_doc/2?if_seq_no=21&if_primary_term=6 
{
	"name": "李四xxx"
}

如果版本号不对,会抛出版本冲突异常,如下图:
在这里插入图片描述

5.文档批量操作

要求

bulk 对 JSON串 有着严格的要求。每个JSON串不能换行 ,只能放在同一行,同时, 相邻的JSON串之间必须要有换行 (Linux下是
;Window下是
)。bulk的每个操作必须要一对JSON串(delete语法除外)

action要求

行为 解释
create 如果文档不存在就创建,但如果文档存在就返回错误 包含 。POSt和PUT 两种操作
index 如果文档不存在就创建,如果文档存在就更新,版本_version 会加1
update 更新一个文档,如果文档不存在就返回错误
delete 删除一个文档,如果要删除的文档id不存在,就返回错误

最大处理数据量

Bulk会把将要处理的数据载入内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值,它取决于你的硬件,你的文档大小以及复杂性,你的索引以及搜索的负载。
一般建议是1000-5000个文档,大小建议是5-15M,默认不能超过100M

优点

  • 支持在一次API调用中,对不同的索引进行操作
  • 可以在URI中指定Index,也可以在请求的Payload中进行
  • 操作中单条操作失败,并不会影响其他操作
  • 返回结果包括了每一条操作执行的结果

批量API

混合处理
# bulk批量的混合操作,一般不推荐这种使用,项目中也用的极少

PUT /_bulk
{ "create" : { "_index" : "ad", "_id" : "6" }}
{ "doc" : {"name" : "bulk"}}
{ "index" : { "_index" : "ad", "_id" : "6" }}
{ "doc" : {"name" : "bulk"}}
{ "delete":{ "_index" : "ad", "_id" : "1"}}
{ "update":{ "_index" : "ad", "_id" : "3"}}
{ "doc" : {"name" : "huawei p20"}}
批量增加API
POST /example/_bulk
{"index": {"_id": 1}}
{"id":1, "name":"admin", "counter":10, "tags":["red", "black"]}
{"index": {"_id": 2}}
{"id":2, "name":"张三", "counter":20, "tags":["green", "purple"]}
{"index": {"_id": 3}}
{"id":3, "name":"李四", "counter":30, "tags":["red", "blue"]}
{"index": {"_id": 4}}
{"id":4, "name":"tom", "counter":40, "tags":["orange"]}
批量修改API
# 批量修改
POST /example/_bulk
{"update": {"_id": 1}}
{"doc": {"id":1, "name": "admin-02", "counter":11}}
{"update": {"_id": 2}}
{"script":{"lang":"painless","source":"ctx._source.counter += params.num","params":
{"num":2}}}
{"update":{"_id": 3}}
{"doc": {"name": "test3333name", "counter": 999}}
{"update":{"_id": 4}}
{"doc": {"name": "test444name", "counter": 888}, "doc_as_upsert" : true}
批量删除API
# 批量删除
POST /example/_bulk
{"delete": {"_id": 1}}
{"delete": {"_id": 2}}
{"delete": {"_id": 3}}
{"delete": {"_id": 4}}
批量读取之mget

es的批量查询可以使用mget和msearch两种。其中mget是需要我们知道它的
id,可以指定不同的index,也可以指定返回值source。msearch可以通过字段
查询来进行一个批量的查找

# 通过ID批量获取不同index的数据
GET _mget
    "docs": [
        {
            "_index": "example",
            "_type": "docs",
            "_id": "1"
        },
        {
            "_index": "example",
            "_type": "docs",
            "_id": "2"
        },
        {
            "_index": "example_test",
            "_type": "docs",
            "_id": "1"
        },
        {
            "_index": "example_test",
            "_type": "docs",
            "_id": "2"
        }
    ]

# 通过ID批量获取相同index的数据
GET example/docs/_mget
{
    "docs": [
        {
            "_id": "1"
        },
        {
            "_id": "2"
        },
        {
            "_id": "3"
        }
    ]
}
批量读取之msearch

在_msearch中,请求格式和bulk类似。查询一条数据需要两个对象,第一个设置index和
type,第二个设置查询语句。查询语句和search相同。如果只是查询一个index,我们可以
在url中带上index,这样,如果查该index可以直接用空对象表示

  • 严格按照格式组装数据,一条语句一行,最后必须以换行符(
    )结尾
  • header和body是成对出现,即使header无内容也要保留“{}”并与换行结束
# 请求格式(JSON)
GET/<indexName>[/<typeName>]/_msearch
{}

body

{}

body


# 指定index
POST /my_test1/_msearch
{}
{"query":{"match_all":{}}}
{}
{"query":{"match":{"name":"张三"}}}

# 多个index
POST /_msearch
{"index":"my_test1"}
{"query":{"match_all":{}}}
{"index":"my_test2"}
{"query":{"match":{"name":"赵六"}}}

6.Rest风格查询

ES的两种查询方式

  • REST风格的请求URI,直接将参数带过去
  • 封装到request body中,这种方式可以定义更加易读的JSON格式,也叫DSL查询

示例

#通过URI搜索,使用“q”指定查询字符串,“query string syntax” KV键值对

# 条件查询, 如要查询age等于28岁的 _search?q=*:***
GET /es_db/_doc/_search?q=age:28

# 范围查询, 如要查询age在25至26岁之间的 _search?q=***[** TO **] 注意: TO 必
须为大写
GET /es_db/_doc/_search?q=age[25 TO 26]


#查询年龄小于等于28岁的 :<=
GET /es_db/_doc/_search?q=age:<=28

# 查询年龄大于28前的 :>
GET /es_db/_doc/_search?q=age:>28

# 分页查询 from=*&size=*
GET /es_db/_doc/_search?q=age[25 TO 26]&from=0&size=1

# 对查询结果只输出某些字段 _source=字段,字段
GET /es_db/_doc/_search?_source=name,age

# 对查询结果排序 sort=字段:desc/asc
GET /es_db/_doc/_search?sort=age:desc