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集群。创建索引时,可以指定以下内容:
- 索引设置
- 索引中字段的映射
- 索引别名
# 创建索引 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
文档删除和修改原理说明
- Elasticsearch执行删除操作时,ES先标记文档为deleted状态,而不是直接物理删除。当ES存储空间不足或工作空闲时,才会执行物理删除操作
- 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