本文发布链接地址: https://www.jianshu.com/p/0ccadf8eb3c5
Elasticsearch RESTFul API
API 基本格式
在命令行访问 集群的 API 的格式如下:
$curl -X
':////?' -d ''
简单解释一下命令的各个部分:
- VERB : 请求的方法,包括 GET/POST/PUT/DELETE/HEAD
- portocol : 协议类型, http 或者 https
- host:port : Elasticsearch 节点所在的主机名或 IP 和端口,比如:本地的 '127.0.0.1:9200'
- path : 表示索引名、类型、文档 ID 组成的路径,比如: /logstash-2017.08.09/log/1
- operation_name : 要执行的操作的名称,比如: _search, _count 等
- query_string : 这是一个在查询参数中指定的可选参数。比如: pretty 用于输出 JSON 格式的数据
- body : 用于查询的请求体,正文文本,在这里可以写上具体的匹配条件等
示例:
curl -XGET 'http://localhost:9200/logstash-2017.09.09'/_search?pretty
表示通过 GET 方法,http 的协议向本地 es 的节点发送查询请求,请求的索引是 logstash-2017.09.09
并且查询结果以 JSON 格式输出
列出集群中所有可用的索引
curl -XGET 'http://localhost:9200/_cat/indices?v'
列出集群中所有节点
curl -XGET 'http://localhost:9200/_cat/nodes?v'
创建
比如我们可以创建一个索引
索引名必须是小写字母
一个示例:
在一个索引的索引信息中的 "mappings" 字段表示了此索引是否是结构化的
创建一个结构化的索引
创建索引需要用到 PUT 方法
curl 代码:
curl -XPUT 172.16.153.129:9200/people -d '
{
"settings":{
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings":{
"man":{
"properties":{
"name":{ "type":"text"},
"country":{"type":"keyword"},
"age":{"type":"integer"},
"date":{"type":"date","format":"yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"}
}
},
"woman":{
}
}
}'?pretty
postman 软件代码:
[图片上传中...(image.png-6a5690-1574297405863-0)]
注意把 # 已经后面的内容删掉
{
"settings":{
"number_of_shards": 3, # 索引的分片数
"number_of_replicas": 1 # 索引的备份数
},
"mappings":{ # 指定此索引为结构化的索引
"man":{
"properties":{
"name":{ "type":"text"},
"country":{"type":"keyword"},
"age":{"type":"integer"},
"date":{"type":"date","format":"yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"}
}
},
"woman":{
}
}
}
插入数据
插入数据分为指定 文档 ID 插入和自动创建文档ID插入
指定文档 ID 使用 PUT 方法
自动创建文档 ID 使用 POST 方法
- postman 使用指定 文档ID 的方法插入数据(PUT)
[图片上传失败...(image-346b77-1574297355287)]
- postman 让 elasticsearch 自动产生文档ID 的方法插入数据(POST)
==自动产生文档ID时,就不需要指定文档 ID 了==
- curl 代码使用 POST 方法让 elasticsearch 自动创建创建文档ID来插入数据
[elk@ansible config]$ curl -XPOST 172.16.153.129:9200/people/man/ -d '
{"name":"大鲨鱼",
"country":"China",
"age": 36,
"date": "1998-06-07"
}'
# 下面是返回的信息
{"_index":"people","_type":"man","_id":"AV-jqE7yEGrD8HzLMoAL","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"created":true}
修改数据
直接修改
curl -XPOST 172.16.153.129:9200/people/man/1/_update -d '
{
"doc":{
"age": 23
}
}'
_update 关键字 说明要修改数据
doc 关键字 说明要修改的是文档
通过脚本修改,支持多种脚本语言,也有自己的脚本语言
请求头和直接修改一样
请求体代码:
{
"script":{ # 指明使用脚本修改
"lang": "painless", # 指定使用的脚本语言, painless 是elasticsearch自己的脚本语言
"inline": "ctx._source.age += 10" # inline 关键字指定了脚本的内容
}
}
也可以把参数写在脚本内容的外面
{
"script":{
"lang": "painless",
"inline": "ctx._source.age = params.age",
"params": {
"age": 18
}
}
}
删除操作
- 删除一个文档
curl 代码
[elk@ansible config]$ curl -XDELETE 172.16.153.129:9200/people/man/1?pretty
{
"found" : false,
"_index" : "people",
"_type" : "man",
"_id" : "1",
"_version" : 1,
"result" : "not_found",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
}
}
- 删除一个索引
==当一个索引被删除后,他所有的数据也会被同时被删除==
curl 代码
删除索引,只需要使用 DELETE 方法,在请求头的 url 中指明索引名即可
[elk@ansible config]$ curl -XDELETE 172.16.153.129:9200/people?pretty
{
"acknowledged" : true
}
空搜索
搜索API的最基础的形式是没有指定任何查询的空搜索 ,它简单地返回集群中所有索引下的所有文档
curl 代码
curl -XGET 172.16.153.129:9200/_search?pretty
返回的部分数据:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 301000,
"max_score": 1,
"hits": [
{
"_index": "logstash-2017.11.04",
"_type": "log",
"_id": "AV-JY_UJfYCoiZimXUZz",
"_score": 1,
"_source": {
"request": "http://123.207.95.27:61180/upload/trans/ff/09/650827/html5/data/img19.png",
"region_code": "11",
"longitude": 116.3883
},
"offset": 352852504,
"auth": "-",
"ident": "-",
"input_type": "log",
"verb": "GET",
"source": "/var/log/nginx/www_eeo_cn.access.log-20170718",
"message": "12"
"type": "log",
"tags": [
"beats_input_codec_plain_applied"
],
"referrer": "\"http://123.207.95.27:61180/upload/trans/ff/09/650827/html5/index.html\"",
"@timestamp": "2017-11-04T23:35:47.664Z",
"response": "304",
"bytes": "0",
"clientip": "123.207.95.27",
"@version": "1",
"beat": {
"name": "ansible",
"hostname": "ansible",
"version": "5.6.3"
},
"host": "ansible",
"httpversion": "1.1",
"timestamp": "18/Jul/2017:18:57:53 +0800"
}
},
]
}
}
关键字段说明
hits
返回结果中最重要的部分是 hits ,它 包含 total 字段来表示匹配到的文档总数,并且一个 hits 数组包含所查询结果的前十个文档。
在 hits 数组中每个结果包含文档的 _index 、 _type 、 _id ,加上 _source 字段。这意味着我们可以直接从返回的搜索结果中使用整个文档。这不像其他的搜索引擎,仅仅返回文档的ID,需要你单独去获取文档。
每个结果还有一个 _score ,它衡量了文档与查询的匹配程度。默认情况下,首先返回最相关的文档结果,就是说,返回的文档是按照 _score 降序排列的。在这个例子中,我们没有指定任何查询,故所有的文档具有相同的相关性,因此对所有的结果而言 1 是中性的 _score 。
max_score 值是与查询所匹配文档的 _score 的最大值
took
took 值告诉我们执行整个搜索请求耗费了多少毫秒。
shards编辑
_shards 部分 告诉我们在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。正常情况下我们不希望分片失败,但是分片失败是可能发生的。如果我们遭遇到一种灾难级别的故障,在这个故障中丢失了相同分片的原始数据和副本,那么对这个分片将没有可用副本来对搜索请求作出响应。假若这样,Elasticsearch 将报告这个分片是失败的,但是会继续返回剩余分片的结果
timeout编辑
timed_out 值告诉我们查询是否超时。默认情况下,搜索请求不会超时。 如果低响应时间比完成结果更重要,你可以指定 timeout 为 10 或者 10ms(10毫秒),或者 1s(1秒)
GET /_search?timeout=10ms
==应当注意的是 timeout 不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接。在后台,其他的分片可能仍在执行查询即使是结果已经被发送了。==
同时对多个索引和多个类型进行搜索
/_search
在所有的索引中搜索所有的类型
/gb/_search
在 gb 索引中搜索所有的类型
/gb,us/_search
在 gb 和 us 索引中搜索所有的文档
/g*,u*/_search
在任何以 g 或者 u 开头的索引中搜索所有的类型
/gb/user/_search
在 gb 索引中搜索 user 类型
/gb,us/user,tweet/_search
在 gb 和 us 索引中搜索 user 和 tweet 类型
/_all/user,tweet/_search
在所有的索引中搜索 user 和 tweet 类型
当在单一的索引下进行搜索的时候,Elasticsearch 转发请求到索引的每个分片中,可以是主分片也可以是副本分片,然后从每个分片中收集结果。多索引搜索恰好也是用相同的方式工作的--只是会涉及到更多的分片。
==搜索一个索引有五个主分片和搜索五个索引各有一个分片准确来所说是等价的。==
对查询到的结果分页
Elasticsearch 接受 from 和 size 参数:
size
显示每次应该返回的结果数量,默认是 10
from
从那个下标索引号开始,默认是 0
因为返回的 hits 是一个数组(列表),所以这里指的是下标,下标从 0 开始计数的。
# 每次返回 5 条数据
curl -XGET '172.16.153.129:9200/_search?size=5&pretty'
# 每次返回 2 条数据,但是从第 6(下标是 5) 条开始
curl -XGET 172.16.153.129:9200/_search?size=2&from=5pretty
考虑到分页过深以及一次请求太多结果的情况,结果集在返回之前先进行排序。 但请记住一个请求经常跨越多个分片,每个分片都产生自己的排序结果,这些结果需要进行集中排序以保证整体顺序是正确的
在分布式系统中,对结果排序的成本随分页的深度成指数上升。这就是 web 搜索引擎对任何查询都不要返回超过 1000 个结果的原因。
映射
为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。
Elasticsearch 支持 如下简单域类型:
字符串: string
整数 : byte, short, integer, long
浮点数: float, double
布尔型: boolean
日期: date
动态映射
默认 es 会通过 JSON 中基本数据类型,尝试猜测域类型,使用如下规则:
JSON type | JSON type |
---|---|
布尔型: true 或者 false | boolean |
数字数据类型:1,1.2 | long,integer,short,byte,double,float,half_float,scaled_float |
日期数据类型 | date |
字符串 | text 和 keyword |
范围数据类型 | integer_range,float_range,long_range,double_range,date_range |
查询映射
获取索引 logstash* 中类型为 log 的映射
[elk@ansible ~]$ curl -XGET '172.16.153.129:9200/logstash*/_mapping/log/?pretty'
==错误的映射,例如 将 age 域映射为 string 类型,而不是 integer ,会导致查询出现令人困惑的结果。==
查询表达式(Query DSL)
查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。
要使用这种查询表达式,只需将查询语句传递给 query 参数:
- 基本语法
GET /_search
{
"query": YOUR_QUERY_HERE
}
- curl 语法:
查询所有,即空查询
curl -XGET '172.16.153.129:9200/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
}
}
'
与 "match_all" 对应的是 "match_none" 完全不匹配的意思
Elasticsearch提供了基于JSON的完整查询DSL来定义查询。将DSL查询看作查询的AST,由两种类型的子句组成:
叶子查询子句
叶查询子句中寻找一个特定的值在某一特定领域,如 match,term或 range查询。这些查询可以自己使用。
复合查询子句
复合查询子句包装其他叶或复合查询,并用于以逻辑方式(例如bool或dis_max查询)组合多个查询 ,或者改变它们的行为(如 constant_score查询)。
查询子句的行为有所不同,具体取决于在查询上下文还是过滤器上下文中使用它们
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
- 该query参数表示查询上下文。
- query 使用了 bool 和两个 match 子句查询相关内容,这意味着它们被用来评定每个文档如何匹配
- filter参数指示过滤器上下文。
- filter 下的 term 和 range 子句,会过滤出不匹配的文件,但不会影响匹配文件的分数。
提示:
在查询上下文中使用查询子句来处理影响匹配文档分数(即文档匹配程度如何)的条件,并在过滤器上下文中使用所有其他查询子句。
全文匹配
match
执行全文查询的标准查询,包括模糊匹配和短语或近似查询。
match_phrase
与match查询类似,但用于匹配精确短语或单词近似匹配。
match_phrase_prefix
像match_phrase查询一样,但在最后一个单词上做了通配符搜索。
multi_match
match查询 的多字段版本。
common_terms
一个更专门的查询,让更多的优先选择不常见的单词。
query_string
支持紧凑的Lucene 查询字符串语法,允许您在单个查询字符串中指定AND | OR | NOT条件和多字段搜索。
仅供专家用户使用。
simple_query_string
query_string适合直接向用户公开 的语法更简单,更健壮的版本。