999 - Elasticsearch 快速上手
Elasticsearch REST API
Elasticsearch提供了全面强大的REST API:
- 检查集群、节点、索引的健康、状态以及统计信息。
- 管理你的集群、节点和索引数据、元数据。
- 对索引进行CRUD。
- 执行分页、排序、过滤、脚本编写、聚合以及其他高级搜索。
Elasticsearch请求格式:<HTTP Verb> /<Index>/<Type>/<ID>
文档说明
- 学习的是Elasticsearch v6.7.1。
- 示例都是用的Kibana,如果不明白Kibana可以看我的或者官网以及其他人的Kibana教程,只需要看DevTools如何使用暂时就够了,也可以用Postman、RestletClient、curl等,能发送REST请求的都可以。
快速入门示例
集群信息
集群健康值:
-
green
:一切正常。(集群功能齐全) -
yellow
:所有数据可用,一些副本尚未分配。(集群功能齐全) -
red
:一些数据由于某种原因不可用。(集群部分功能可用)
注意:状态为red时仍然提供搜索服务(在可用的分片中搜索),但你需要尽快的去修复它。
GET /_cat/health?v
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1555378987 01:43:07 elasticsearch green 1 1 4 4 0 0 0 0 - 100.0%
节点信息
列出所有节点。
GET /_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1 49 73 11 mdi * m9Y7FJV
索引信息
列出所有索引。
GET /_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .monitoring-es-6-2019.04.16 IND0TKuCQsyHTH2FDE1zdg 1 0 5478 36 2.7mb 2.7mb
green open .kibana_1 XTsD7vQ7QbukbJpFlkfLQQ 1 0 4 0 14.4kb 14.4kb
green open .kibana_task_manager 0G59n4AWQzSxJ6YSHBDPnA 1 0 2 0 12.5kb 12.5kb
green open .monitoring-kibana-6-2019.04.16 -SZdui1tTw-srkqmUxzQHw 1 0 684 0 309.2kb 309.2kb
创建索引
创建一个索引:名叫customer,2个分片,0副本。
# PUT /customer
# PUT /customer?pretty
PUT /customer?pretty
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
}
}
注意:默认是5个分片1个副本,如果只有一个节点,副本分片就会没有地方分配,集群状态就会为YELLOW。
解释一下pretty(pretty-printed),直接看示例
添加pretty时:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "customer"
}
没有添加pretty时:
{"acknowledged":true,"shards_acknowledged":true,"index":"customer"}
删除索引
删除customer索引。
DELETE /customer?pretty
新增文档
使用PUT新增:id为1,name字段值为“Put Add”。
另外,在新增文档时可以不提前创建好索引与类型,elasticsearch会自动帮你创建。
PUT /customer/_doc/1?pretty
{
"name": "Put Add"
}
响应
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
查询刚才新增的数据
GET /customer/_doc/1?pretty
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Put Add"
}
}
使用POST新增:自动生成id
POST /customer/_doc?pretty
{
"name": "Post Add"
}
响应
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "RYeuJGoB_H2WuLZOyvLU",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
更新文档
Elasticsearch实际上并不是更新文档,而是创建新文档。
使用PUT更新:ID相同时会替换,也就相当于更新。
PUT /customer/_doc/1?pretty
{
"name": "PUT Update"
}
响应:_version、result改变了。
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
Post更新
1.更新字段
POST /customer/_doc/1/_update?pretty
{
"doc": {
"name": "Post Update"
}
}
2.更新的同时,新增一个字段。
POST /customer/_doc/1/_update?pretty
{
"doc": {
"name": "Baozi",
"age": "21"
}
}
3.使用脚本更新,将年龄增加5岁
POST /customer/_doc/1/_update?pretty
{
"script": "ctx._source.age += 5"
}
删除文档
DELETE /customer/_doc/1?pretty
DELETE /customer/_doc/RYeuJGoB_H2WuLZOyvLU?pretty
批量操作
批量操作类型:
- index:不存在就创建,已存在就更新
- create:创建
- delete:删除
- update:更新
创建两个文档。
POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name":"Baozi1"}
{"index":{"_id":"2"}}
{"name":"Baozi2"}
更新文档1,删除文档2
POST /customer/_doc/_bulk?pretty
{"update":{"_id":"1"}}
{"doc":{"name":"Baozi1 Updated"}}
{"delete":{"_id":"2"}}
批量操作不会因为其中一个失败中断后续的操作。结束后会按顺序返回响应信息。
示例:增删改报错不会中断,操作类型写错会忽略执行。
POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name":"Baozi1"}
{"create":{"_id":"1"}}
{"name":"Baozi1"}
{"indexed":{"_id":"2"}}
{"name":"Baozi2"}
{"update":{"_id":"10000"}}
{"doc":{"name":"Baozi10000"}}
{"delete":{"_id":"100000"}}
{"delete":{"_id":"100001"}}
快速入门查询示例
导入数据
使用官方提供的样本数据,格式:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
-
将数据复制到文件account.json,之后在文件末尾新起一空行,否则报错
bulk request must be terminated by newline
-
创建索引
PUT /bank?pretty
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
}
}
- 导入到ES
注意@
必须要有,否则也会报错bulk request must be terminated by newline
$ curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@你的文件路径"
URI Search
q
:要查询的字段
sort
:用来排序的字段,asc升序,desc倒序
GET /bank/_search?q=*&sort=account_number:asc&pretty
返回结果中的字段:
took
:ES执行查询的时间,毫秒
timed_out
:告诉我们搜索是否超时
_shards
:搜索了多少个分片,以及搜索成功/失败的个数。
hits
:查询结果
hits.total
:符合搜索条件的总数
hits.hits
:搜索结果
hits.hits.sort
:用来排序的字段,如果没有指定则按分数排序,就不会有这一部分。
hits.max_score
、hits.hits._score
:相关性分数,分数越高表明与搜索条件越接近。
Request Body Search
示例
match_all
:match_all查询,查询所有字段
sort
:用来排序的字段。
from
:从哪里开始,默认从0开始。
size
:查多少个,默认10个。
_source
: 指定返回的字段。
GET /bank/_search
{
"query": {"match_all": {}},
"sort": [
{
"account_number":"asc"
}
],
"from": 10,
"size": 2,
"_source": ["account_number","balance"]
}
match
查询address包含mill
或lane
的。
提示:ES存数据时会将mill lane
分成mill
和lane
做一个分词,想要查询必须包含mill lane
可以看下一条match_phrase的示例。
GET /bank/_search
{
"query": {
"match": {
"address": "mill lane"
}
}
}
match_phrase
查询address包含mill lane
的。
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "mill lane"
}
}
}
bool
bool查询的好处在于可以组合多个条件(match、match_phrase等)。
must
:满足所有匹配条件。
should
:满足其中一个匹配条件。
must_not
:必须不满足条件。
filter
:过滤内容,并且不进行相关性算分。
must:查询同时包含mill
和lane
的address。
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"address": "lane"
}
}
]
}
}
}
should:查询包含mill
或lane
的address。
GET /bank/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"address": "lane"
}
}
]
}
}
}
must_not: 查询不包含
GET /bank/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"address": "mill"
}
},
{
"match": {
"address": "lane"
}
}
]
}
}
}
组合match、must_not等:查询40岁并且不居住在ID(Idaho的缩写)的人。
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "40"
}
}
],
"must_not": [
{
"match": {
"state": "ID"
}
}
]
}
}
}
filter:对地址包含mill
或lane
的,进行过滤,取余额大于30000的。
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"address": "mill lane"
}
}
],
"filter": {
"range": {
"balance": {
"gte": 30000
}
}
}
}
}
}
聚合查询
示例一:聚合示例,按state分组,返回前100条聚合结果。
说明:外边一个size设为0,是为了不返回文档只返回聚合结果;field字段下面的size表示terms聚合返回多少条聚合结果,默认10条。
GET /bank/_search
{
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"size": 100
}
}
},
"size": 0
}
示例二:嵌套聚合,在上一个示例的基础上,计算每个州的平均余额。
GET /bank/_search
{
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"size": 100
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
示例三:聚合排序,接着上一个示例,按照平均余额排序。
GET /bank/_search
{
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"size": 100,
"order": {
"average_balance": "desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
},
"size": 0
}
示例四:按照年龄分区间,然后再按照性别分组,最后求出每组的平均余额。
GET /bank/_search
{
"aggs": {
"group_by_age": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 29
},
{
"from": 30,
"to": 39
},
{
"from": 40,
"to": 49
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field": "gender.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
},
"size": 0
}