ElasticSearch 常用API
資料操作
官方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":"[email protected]","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":"[email protected]","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不提供此方式需要改原始碼。