3.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),直接看示例<br/>
添加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”。<br/>
另外,在新增文档时可以不提前创建好索引与类型,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更新<br/>
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"}}
批量操作不会因为其中一个失败中断后续的操作。结束后会按顺序返回响应信息。<br/>
示例:增删改报错不会中断,操作类型写错会忽略执行。
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": "[email protected]", "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<br/>
注意@
必须要有,否则也会报错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
:要查询的字段<br/>sort
:用来排序的字段,asc升序,desc倒序<br/>
GET /bank/_search?q=*&sort=account_number:asc&pretty
返回结果中的字段:<br/>took
:ES执行查询的时间,毫秒<br/>timed_out
:告诉我们搜索是否超时<br/>_shards
:搜索了多少个分片,以及搜索成功/失败的个数。<br/>hits
:查询结果<br/>hits.total
:符合搜索条件的总数<br/>hits.hits
:搜索结果<br/>hits.hits.sort
:用来排序的字段,如果没有指定则按分数排序,就不会有这一部分。<br/>hits.max_score
、hits.hits._score
:相关性分数,分数越高表明与搜索条件越接近。<br/>
Request Body Search
示例<br/>match_all
:match_all查询,查询所有字段<br/>sort
:用来排序的字段。<br/>from
:从哪里开始,默认从0开始。<br/>size
:查多少个,默认10个。<br/>_source
: 指定返回的字段。<br/>
GET /bank/_search { "query": {"match_all": {}}, "sort": [ { "account_number":"asc" } ], "from": 10, "size": 2, "_source": ["account_number","balance"] }
match<br/>
查询address包含mill
或lane
的。<br/>
提示:ES存数据时会将mill lane
分成mill
和lane
做一个分词,想要查询必须包含mill lane
可以看下一条match_phrase的示例。
GET /bank/_search { "query": { "match": { "address": "mill lane" } } }
match_phrase<br/>
查询address包含mill lane
的。
GET /bank/_search { "query": { "match_phrase": { "address": "mill lane" } } }
bool<br/>
bool查询的好处在于可以组合多个条件(match、match_phrase等)。<br/>must
:满足所有匹配条件。<br/>should
:满足其中一个匹配条件。<br/>must_not
:必须不满足条件。<br/>filter
:过滤内容,并且不进行相关性算分。<br/>
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 } } } } } }
聚合查询<br/>
示例一:聚合示例,按state分组,返回前100条聚合结果。<br/>
说明:外边一个size设为0,是为了不返回文档只返回聚合结果;field字段下面的size表示terms聚合返回多少条聚合结果,默认10条。<br/>
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 }