数据操作
官方API文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docs.html
中文API文档:https://doc.codingdict.com/elasticsearch/
常用API
curl -XGET 'localhost:9200/_cat/health?v&pretty' #集群健康
curl -XGET 'localhost:9200/_cat/nodes?v&pretty' #查看所有节点
curl -XGET 'localhost:9200/_cat/indices?v&pretty' #查看所有索引
curl -XGET 'http://192.168.0.100:9202/_cluster/stats?pretty' #查看集群详细信息
curl -XPUT 'localhost:9200/customer?pretty&pretty' #创建一个名为 “customer” 的索引
# 索引一个简单的 customer 文档到 customer 索引中,“external” 类型,与一个为 1 的 ID
curl -XPUT 'localhost:9200/customer/external/1?pretty&pretty' -d'
{
"name": "John Doe"
}'
curl -XGET 'localhost:9200/customer/external/1?pretty&pretty' #检索我们刚刚索引的文档
curl -XDELETE 'localhost:9200/customer?pretty&pretty' #删除刚创建的索引
#如果仔细研究上面的命令,可以清楚的看到,如何访问 Elasticsearch 中的数据的 pattern(模式)。该 pattern(模式)可以概括如下 :
<REST Verb> /<Index>/<Type>/<ID>
搜索 API
现在让我们从一些简单的搜索开始。这里两个运行搜索的基本方法 : 一个是通过使用 REST request URI 发送搜索参数,另一个是通过使用 REST request body 来发送它们。请求体的方法可以让您更具有表现力,并且可以在一个更可读的 JSON 格式中定义您的搜索。我们会尝试使用一个 REST request URI 的示例,但是在本教程的其它部分,我们将只使用 REST request body 的方法。
搜索的 REST API 从 _search 的尾部开始。这个示例返回了 bank 索引中的所有文档 :
curl -XGET 'localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty'
首先让我们切开搜索的调用。我们在 bank 索引中执行搜索(_search 尾部),然后 q=参数命令Elasticsearch去匹配索引中所有的文档。pretty 参数,再一次告诉 Elasticsearch 去返回打印漂亮的 JSON** 结果。
响应如下(部分):
{
"took" : 63,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1000,
"max_score" : null,
"hits" : [ {
"_index" : "bank",
"_type" : "account",
"_id" : "0",
"sort": [0],
"_score" : null,
"_source" : {"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"}
}, {
"_index" : "bank",
"_type" : "account",
"_id" : "1",
"sort": [1],
"_score" : null,
"_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
}, ...
]
}
}
在响应中,我们可以看到以下几个部分 :
- took - Elasticsearch 执行搜索的时间(毫秒)
- time_out - 告诉我们搜索是否超时
- _shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
- hits - 搜索结果
- hits.total - 搜索结果
- hits.hits - 实际的搜索结果数组(默认为前 10 的文档)
- sort - 结果的排序 key(键)(没有则按 score 排序)
- score 和max_score -现在暂时忽略这些字段
这里是上面相同的搜索,使用了 REST request body 方法 :
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}'
这里不同的地方是而不是在 URL 中传递 q= **,我们* *POST* 一个 JSON 风格的查询请求体到 _search API。我们将在下一部分讨论这个 JSON** 查询。
需要了解,一旦您搜索的结果被返回,Elasticsearch 完成了这次请求,并且不会维护任何服务端的资源或者结果的 cursor(游标)。这与其它的平台形成了鲜明的对比,例如 SQL,您可能首先获得查询结果的子集,如果您想要使用一些服务端有状态的 cursor(光标)来抓取(或者通过分页)其它的结果,然后您必须再次回到服务器。
新增记录
向指定的 /Index/Type 发送 PUT 请求,就可以在 Index 里面新增一条记录。比如,向/accounts/person
发送请求,就可以新增一条人员记录。
curl -X PUT 'localhost:9200/accounts/person/1' -d '
{
"user": "张三",
"title": "工程师",
"desc": "数据库管理"
}'
服务器返回的 JSON 对象,会给出 Index、Type、Id、Version 等信息。
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{"total":2,"successful":1,"failed":0},
"created":true
}
如果你仔细看,会发现请求路径是/accounts/person/1
,最后的1
是该条记录的 Id。它不一定是数字,任意字符串(比如abc
)都可以。
新增记录的时候,也可以不指定 Id,这时要改成 POST 请求。
$ curl -X POST 'localhost:9200/accounts/person' -d '
{
"user": "李四",
"title": "工程师",
"desc": "系统管理"
}'
上面代码中,向/accounts/person
发出一个 POST 请求,添加一个记录。这时,服务器返回的 JSON 对象里面,_id
字段就是一个随机字符串。
{
"_index":"accounts",
"_type":"person",
"_id":"AV3qGfrC6jMbsbXb6k1p",
"_version":1,
"result":"created",
"_shards":{"total":2,"successful":1,"failed":0},
"created":true
}
注意,如果没有先创建 Index(这个例子是accounts
),直接执行上面的命令,Elastic 也不会报错,而是直接生成指定的 Index。所以,打字的时候要小心,不要写错 Index 的名称。
查看记录
向/Index/Type/Id
发出 GET 请求,就可以查看这条记录。
curl 'localhost:9200/accounts/person/1?pretty=true'
上面代码请求查看/accounts/person/1
这条记录,URL 的参数pretty=true
表示以易读的格式返回。
返回的数据中,found
字段表示查询成功,_source
字段返回原始记录。
{
"_index" : "accounts",
"_type" : "person",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理"
}
}
如果 Id 不正确,就查不到数据,found
字段就是false
。
$ curl 'localhost:9200/weather/beijing/abc?pretty=true'
{
"_index" : "accounts",
"_type" : "person",
"_id" : "abc",
"found" : false
}
删除记录
删除记录就是发出 DELETE 请求。
curl -X DELETE 'localhost:9200/accounts/person/1'
这里先不要删除这条记录,后面还要用到。
更新记录
更新记录就是使用 PUT 请求,重新发送一次数据。
$ curl -X PUT 'localhost:9200/accounts/person/1' -d '
{
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理,软件开发"
}'
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_version":2,
"result":"updated",
"_shards":{"total":2,"successful":1,"failed":0},
"created":false
}
上面代码中,我们将原始数据从"数据库管理"改成"数据库管理,软件开发"。 返回结果里面,有几个字段发生了变化。
"_version" : 2,
"result" : "updated",
"created" : false
可以看到,记录的 Id 没变,但是版本(version)从1
变成2
,操作类型(result)从created
变成updated
,created
字段变成false
,因为这次不是新建记录。
数据查询
返回所有记录
使用 GET 方法,直接请求/Index/Type/_search
,就会返回所有记录。
curl 'localhost:9200/accounts/person/_search'
{
"took":2,
"timed_out":false,
"_shards":{"total":5,"successful":5,"failed":0},
"hits":{
"total":2,
"max_score":1.0,
"hits":[
{
"_index":"accounts",
"_type":"person",
"_id":"AV3qGfrC6jMbsbXb6k1p",
"_score":1.0,
"_source": {
"user": "李四",
"title": "工程师",
"desc": "系统管理"
}
},
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_score":1.0,
"_source": {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理,软件开发"
}
}
]
}
}
上面代码中,返回结果的 took
字段表示该操作的耗时(单位为毫秒),timed_out
字段表示是否超时,hits
字段表示命中的记录,里面子字段的含义如下。
-
total
:返回记录数,本例是2条。 -
max_score
:最高的匹配程度,本例是1.0
。 -
hits
:返回的记录组成的数组。
返回的记录中,每条记录都有一个_score
字段,表示匹配的程序,默认是按照这个字段降序排列。
全文搜索
Elastic 的查询非常特别,使用自己的查询语法,要求 GET 请求带有数据体。
curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "软件" }}
}'
上面代码使用 Match 查询,指定的匹配条件是desc
字段里面包含"软件"这个词。返回结果如下。
{
"took":3,
"timed_out":false,
"_shards":{"total":5,"successful":5,"failed":0},
"hits":{
"total":1,
"max_score":0.28582606,
"hits":[
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_score":0.28582606,
"_source": {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理,软件开发"
}
}
]
}
}
Elastic 默认一次返回10条结果,可以通过size
字段改变这个设置。
curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "管理" }},
"size": 1
}'
上面代码指定,每次只返回一条结果。
还可以通过from
字段,指定位移。
curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "管理" }},
"from": 1,
"size": 1
}'
上面代码指定,从位置1开始(默认是从位置0开始),只返回一条结果。
逻辑运算
如果有多个搜索关键字, Elastic 认为它们是or
关系。
curl 'localhost:9200/accounts/person/_search' -d '
{
"query" : { "match" : { "desc" : "软件 系统" }}
}'
上面代码搜索的是软件 or 系统
。
如果要执行多个关键词的and
搜索,必须使用布尔查询。
curl 'localhost:9200/accounts/person/_search' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "desc": "软件" } },
{ "match": { "desc": "系统" } }
]
}
}
}'
批处理
除了可以索引,更新,和删除单个的文档之外,Elasticsearch 还提供了使用 _bulk
API 来执行上面任何操作的批量方式的能力。这个功能是非常重要,它提供了一种非常有效的机制,以尽可能减少网络返回且尽可能快的执行多个操作。
作为一个简单的例子,在一个批量操作中下面调用且索引了两个文档(ID 1 - John Doe 和 ID 2 - Jane Doe):
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty&pretty' -d'
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
'
这个例子使用一个批量操作更新了第一个文档(ID 为 1),然后删除了第二个文档(ID 为 2) :
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty&pretty' -d'
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
'
请注意上面的删除操作,在它后面没有相关的源文档,因为删除操作只需要文档的 ID 来删除。
该 bulk API 以此按顺序执行所有的 action(动作)。如果一个单个的动作因任何原因而失败,它将继续处理它后面剩余的动作。当 bulk API 返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是不是失败了。
删除文档
curl -XDELETE 'localhost:9200/customer/external/2?pretty&pretty'
请看 Delete By Query API 以删除指定查询匹配到的所有文档。值得注意的是,它是删除一个完整的索引更有效的方式,而不是使用 Delete By Query API 来删除所有的文档。
更新记录
#更新文档
#更新我们先前的文档(ID 为 1),通过修改 name 字段的值为 “Jane Doe” :
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty&pretty' -d'
{
"doc": { "name": "Jane Doe" }
}'
#更新我们先前的文档(ID 为 1),通过修改 name 字段的值为 “Jane Doe”,并且同时添加 age 字段 :
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty&pretty' -d'
{
"doc": { "name": "Jane Doe", "age": 20 }
}'
#更新也是通过使用简单的简本来执行。这个例子演示了使用简本来将 age 加 5 :
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty&pretty' -d'
{
"script" : "ctx._source.age += 5"
}'
#在上面的例子中,ctx._source 代表当前将被更新的源文档。
副本分片操作
# 查看副本分片信息
curl -XGET http://192.168.79.131:9200/shb01/_settings?pretty
#不存在索引shb03时可以指定副本和分片,如果shb03已经存在则只能修改副本
curl -XPUT http://192.168.79.131:9200/shb03-d'{"settings":{"number_of_shards":4,"number_of_replicas":2}}'
#在es中添加索引数据时不需要指定数据类型,es中有自动影射机制,字符串映射为string,数字映射为long。通过mappings可以指定数据类型是否存储等属性。
#查看mapping信息
curl -XGEThttp://192.168.79.131:9200/shb01/_mappings?pretty
分片查询
Es会将数据均衡的存储在分片中,我们可以指定es去具体的分片或节点钟查询从而进一步的实现es极速查询。
- randomizeacross shards: 随机选择分片查询数据,es的默认方式
- _local: 优先在本地节点上的分片查询数据然后再去其他节点上的分片查询,本地节点没有IO问题但有可能造成负载不均问题。数据量是完整的
- _primary:只在主分片中查询不去副本查,一般数据完整。
- _primary_first:优先在主分片中查,如果主分片挂了则去副本查,一般数据完整。
- _only_node:只在指定id的节点中的分片中查询,数据可能不完整。
- __prefer_node : 优先在指定你给节点中查询,一般数据完整。
- _shards : 在指定分片中查询,数据可能不完整
- _only_nodes : 可以自定义去指定的多个节点查询,es不提供此方式需要改源码。