Elasticsearch 是一個分佈式的 RESTful 風格的搜索和數據分析引擎。html
Elasticsearch是一個高度可伸縮的開源全文搜索和分析引擎。它容許您快速和接近實時地存儲、搜索和分析大量數據。node
這裏有一些使用Elasticsearch的用例:git
Near Realtime (NRT)github
Elasticsearch是一個近乎實時的搜索平臺。這意味着從索引文檔到能夠搜索的時間只有輕微的延遲(一般是1秒)。json
Cluster數組
集羣是一個或多個節點(服務器)的集合,它們共同保存你的整個數據,並提供跨全部節點的聯合索引和搜索功能。一個集羣由一個惟一的名稱標識,默認這個惟一標識的名稱是"elasticsearch"。這個名稱很重要,由於若是節點被設置爲按其名稱加入集羣,那麼節點只能是集羣的一部分。服務器
確保不要在不一樣的環境中用相同的集羣名稱,不然可能致使節點加入到錯誤的集羣中。例如,你可使用"logging-dev", "logging-test", "logging-prod"分別用於開發、測試和正式集羣的名字。網絡
Nodeapp
節點是一個單獨的服務器,它是集羣的一部分,存儲數據,並參與集羣的索引和搜索功能。就像集羣同樣,節點由一個名稱來標識,默認狀況下,該名稱是在啓動時分配給節點的隨機通用惟一標識符(UUID)。若是不想用默認的節點名,能夠定義任何想要的節點名。這個名稱對於管理來講很重要,由於你但願識別網絡中的哪些服務器對應於你的Elasticsearch集羣中的哪些節點。curl
一個節點能夠經過配置集羣名稱來加入到一個特定的集羣中。默認狀況下,每一個節點都被設置加入到一個名字叫"elasticsearch"的集羣中,這就意味着若是你啓動了不少個節點,而且假設它們彼此能夠互相發現,那麼它們將自動造成並加入到一個名爲"elasticsearch"的集羣中。
一個集羣能夠有任意數量的節點。此外,若是在你的網絡上當前沒有運行任何節點,那麼此時啓動一個節點將默認造成一個單節點的名字叫"elasticsearch"的集羣。
Index
索引是具備某種類似特徵的文檔的集合。例如,你能夠有一個顧客數據索引,產品目錄索引和訂單數據索引。索引有一個名稱(必須是小寫的)標識,該名稱用於在對其中的文檔執行索引、搜索、更新和刪除操做時引用索引。
Document
文檔是能夠被索引的基本信息單元。文檔用JSON表示。
Shards & Replicas
一個索引可能存儲大量數據,這些數據能夠超過單個節點的硬件限制。例如,一個包含10億條文檔佔用1TB磁盤空間的索引可能不適合在單個節點上,或者可能太慢而不能單獨處理來自單個節點的搜索請求。
爲了解決這個問題,Elasticsearch提供了將你的索引細分爲多個碎片(或者叫分片)的能力。在建立索引時,能夠簡單地定義所需的分片數量。每一個分片自己就是一個功能徹底獨立的「索引」,能夠駐留在集羣中的任何節點上。
分片之因此重要,主要有兩個緣由:
在一個網絡/雲環境中隨時都有可能出現故障,強烈推薦你有一個容災機制。Elasticsearch容許你將一個或者多個索引分片複製到其它地方,這被稱之爲副本。
複製之因此重要,有兩個主要緣由:
總而言之,每一個索引均可以分割成多個分片。索引也能夠被複制零(意味着沒有副本)或更屢次。一旦被複制,每一個索引都將具備主分片(被複制的原始分片)和副本分片(主分片的副本)。在建立索引時,能夠爲每一個索引定義分片和副本的數量。建立索引後,您能夠隨時動態地更改副本的數量,但不能更改過後分片的數量。
在默認狀況下,Elasticsearch中的每一個索引都分配了5個主分片和1個副本,這意味着若是集羣中至少有兩個節點,那麼索引將有5個主分片和另外5個副本分片(PS:這5個副本分片組成1個完整副本),每一個索引總共有10個分片。
(畫外音:副本是針對索引而言的,同時須要注意索引和節點數量沒有關係,咱們說2個副本指的是索引被複制了2次,而1個索引可能由5個分片組成,那麼在這種狀況下,集羣中的分片數應該是 5 × (1 + 2) = 15 )
tar -zxf elasticsearch-6.3.2.tar.gz cd elasticsearch-6.3.2/bin ./elasticsearch
注意:不能以root用戶運行elasticsearch
By default, Elasticsearch uses port 9200 to provide access to its REST API. This port is configurable if necessary.
檢查Elasticsearch是否正在運行:
curl http://localhost:9200/
請求:
curl -X GET "localhost:9200/_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 1533625274 15:01:14 elasticsearch green 1 1 0 0 0 0 0 0 - 100.0%
咱們能夠看到,咱們命名爲「elasticsearch」的集羣如今是green狀態。
不管什麼時候咱們請求集羣健康時,咱們會獲得green, yellow, 或者 red 這三種狀態。
從上面的響應中咱們能夠看到,集羣"elasticsearch"總共有1個節點,0個分片由於尚未數據。
下面看一下集羣的節點列表:
請求:
curl -X GET "localhost:9200/_cat/nodes?v"
響應:
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name 127.0.0.1 15 53 0 0.03 0.03 0.05 mdi * Px524Ts
能夠看到集羣中只有一個節點,它的名字是「Px524Ts」
請求:
curl -X GET "localhost:9200/_cat/indices?v"
響應:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
上面的輸出意味着:咱們在集羣中沒有索引
如今,咱們建立一個名字叫「customer」的索引,而後查看索引:
請求:
curl -X PUT "localhost:9200/customer?pretty"
(畫外音:pretty的意思是響應(若是有的話)以JSON格式返回)
響應:
{ "acknowledged" : true, "shards_acknowledged" : true, "index" : "customer" }
請求:
curl -X GET "localhost:9200/_cat/indices?v"
響應:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open customer rG5fxdruTNmD-bdYIF5zOg 5 1 0 0 1.1kb 1.1kb
結果的第二行告訴咱們,咱們如今有叫"customer"的索引,而且他有5個主分片和1個副本(默認是1個副本),有0個文檔。
可能你已經注意到這個"customer"索引的健康狀態是yellow。回想一下咱們以前的討論,yellow意味着一些副本(還沒有)被分配。
之因此會出現這種狀況,是由於Elasticsearch默認狀況下爲這個索引建立了一個副本。因爲目前咱們只有一個節點在運行,因此直到稍後另外一個節點加入集羣時,纔會分配一個副本(對於高可用性)。一旦該副本分配到第二個節點上,該索引的健康狀態將變爲green。
如今,讓咱們put一些數據到咱們的"customer"索引:
請求:
curl -X PUT "localhost:9200/customer/_doc/1?pretty" -H 'Content-Type: application/json' -d'{"name": "John Doe"}'
響應:
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
從上面的響應能夠看到,咱們在"customer"索引下成功建立了一個文檔。這個文檔還有一個內部id爲1,這是咱們在建立的時候指定的。
須要注意的是,Elasticsearch並不要求你在索引文檔以前就先建立索引,而後才能將文檔編入索引。在前面的示例中,若是事先不存在"customer"索引,Elasticsearch將自動建立"customer"索引。
(畫外音:也就是說,在新建文檔的時候若是指定的索引不存在則會自動建立相應的索引)
如今,讓我從新檢索這個文檔:
請求:
curl -X GET "localhost:9200/customer/_doc/1?pretty"
響應:
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "name" : "John Doe" } }
能夠看到除了"found"字段外沒什麼不一樣,"_source"字段返回了一個完整的JSON文檔。
如今,讓咱們刪除前面建立的索引,而後查看所有索引
請求:
curl -X DELETE "localhost:9200/customer?pretty"
響應:
{ "acknowledged" : true }
接下來,查看一下
curl -X GET "localhost:9200/_cat/indices?v"
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
到如今爲止,咱們已經學習了建立/刪除索引、索引/查詢文檔這四個命令
curl -X PUT "localhost:9200/customer" curl -X PUT "localhost:9200/customer/_doc/1" -H 'Content-Type: application/json' -d'{"name": "John Doe"}' curl -X GET "localhost:9200/customer/_doc/1" curl -X DELETE "localhost:9200/customer"
若是咱們仔細研究上面的命令,咱們實際上能夠看到如何在Elasticsearch中訪問數據的模式。這種模式能夠歸納以下:
<REST Verb> /<Index>/<Type>/<ID>
事實上,每當咱們執行更新時,Elasticsearch就會刪除舊文檔,而後索引一個新的文檔。
下面這個例子展現瞭如何更新一個文檔(ID爲1),改變name字段爲"Jane Doe",同時添加一個age字段:
請求:
curl -X POST "localhost:9200/customer/_doc/1/_update?pretty" -H 'Content-Type: application/json' -d' { "doc": { "name": "Jane Doe", "age": 20 } } '
響應:
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1 }
下面這個例子用腳原本將age增長5
請求:
curl -X POST "localhost:9200/customer/_doc/1/_update?pretty" -H 'Content-Type: application/json' -d' { "script" : "ctx._source.age += 5" } '
在上面例子中,ctx._source引用的是當前源文檔
響應:
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 3, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 2, "_primary_term" : 1 }
刪除文檔至關簡單。這個例子展現瞭如何從"customer"索引中刪除ID爲2的文檔:
請求:
curl -X DELETE "localhost:9200/customer/_doc/2?pretty"
響應:
{ "_index" : "customer", "_type" : "_doc", "_id" : "2", "_version" : 1, "result" : "not_found", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
除了可以索引、更新和刪除單個文檔以外,Elasticsearch還可使用_bulk API批量執行上述任何操做。
這個功能很是重要,由於它提供了一種很是有效的機制,能夠在儘量少的網絡往返的狀況下儘量快地執行多個操做。
下面的例子,索引兩個文檔(ID 1 - John Doe 和 ID 2 - Jane Doe)
請求:
curl -X POST "localhost:9200/customer/_doc/_bulk?pretty" -H 'Content-Type: application/json' -d' {"index":{"_id":"1"}} {"name": "John Doe" } {"index":{"_id":"2"}} {"name": "Jane Doe" } '
響應:
{ "took" : 5, "errors" : false, "items" : [ { "index" : { "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 4, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 3, "_primary_term" : 1, "status" : 200 } }, { "index" : { "_index" : "customer", "_type" : "_doc", "_id" : "2", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1, "status" : 201 } } ] }
接下來的例子展現了,更新第一個文檔(ID爲1),刪除第二個文檔(ID爲2):
請求:
curl -X POST "localhost:9200/customer/_doc/_bulk?pretty" -H 'Content-Type: application/json' -d' {"update":{"_id":"1"}} {"doc": { "name": "John Doe becomes Jane Doe" } } {"delete":{"_id":"2"}} '
響應:
{ "took" : 8, "errors" : false, "items" : [ { "update" : { "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 5, "result" : "updated", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 4, "_primary_term" : 1, "status" : 200 } }, { "delete" : { "_index" : "customer", "_type" : "_doc", "_id" : "2", "_version" : 2, "result" : "deleted", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 2, "_primary_term" : 1, "status" : 200 } } ] }
如今,咱們來從新查看一下索引文檔
curl -X GET "localhost:9200/customer/_doc/1?pretty"
如今咱們已經瞭解了基礎知識,讓咱們嘗試處理一個更真實的數據集。我準備了一個關於客戶銀行帳戶信息的虛構JSON文檔示例。每一個文檔都有如下格式:
{ "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" }
你能夠從這裏下載示例數據
提取它到咱們的當前目錄,而且加載到咱們的集羣中:
新建一個文件accounts.json,而後將數據複製粘貼到該文件中,保存退出
在這個accounts.json文件所在目錄下執行以下命令:
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@accounts.json"
此時,accounts.json中的文檔數據便被索引到"bank"索引下
讓咱們查看一下索引:
請求:
curl "localhost:9200/_cat/indices?v"
響應:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open customer DoM-O7QmRk-6f3Iuls7X6Q 5 1 1 0 4.5kb 4.5kb yellow open bank 59jD3B4FR8iifWWjrdMzUg 5 1 1000 0 474.7kb 474.7kb
能夠看到,如今咱們的集羣中有兩個索引,分別是"customer"和"bank"
"customer"索引,1個文檔,"bank"索引有1000個文檔
如今讓咱們從一些簡單的搜索開始。運行搜索有兩種基本方法:一種是經過REST請求URI發送檢索參數,另外一種是經過REST請求體發送檢索參數。
(畫外音:一種是把檢索參數放在URL後面,另外一種是放在請求體裏面。至關於HTTP的GET和POST請求)
請求體方法容許你更有表現力,也能夠用更可讀的JSON格式定義搜索。
用於搜索的REST API可從_search端點訪問。下面的例子返回"bank"索引中的全部文檔:
curl -X GET "localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty"
讓咱們來剖析一下上面的請求。
咱們在"bank"索引中檢索,q=*參數表示匹配全部文檔;sort=account_number:asc表示每一個文檔的account_number字段升序排序;pretty參數表示返回漂亮打印的JSON結果。
響應結果看起來是這樣的:
{ "took" : 96, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 1000, "max_score" : null, "hits" : [ { "_index" : "bank", "_type" : "_doc", "_id" : "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" }, "sort" : [ 0 ] }, { "_index" : "bank", "_type" : "_doc", "_id" : "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" }, "sort" : [ 1 ] }, { "_index" : "bank", "_type" : "_doc", "_id" : "2", "_score" : null, "_source" : { "account_number" : 2, "balance" : 28838, "firstname" : "Roberta", "lastname" : "Bender", "age" : 22, "gender" : "F", "address" : "560 Kingsway Place", "employer" : "Chillium", "email" : "robertabender@chillium.com", "city" : "Bennett", "state" : "LA" }, "sort" : [ 2 ] }, ...... ] }
能夠看到,響應由下列幾部分組成:
下面是一個和上面相同,可是用請求體的例子:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] } '
區別在於,咱們沒有在URI中傳遞q=*,而是向_search API提供json風格的查詢請求體
很重要的一點是,一旦返回搜索結果,Elasticsearch就徹底完成了對請求的處理,不會在結果中維護任何類型的服務器端資源或打開遊標。這是許多其餘平臺如SQL造成鮮明對比。
Elasticsearch提供了一種JSON風格的語言,您可使用這種語言執行查詢。這被成爲查詢DSL。
查詢語言很是全面,乍一看可能有些嚇人,但實際上最好的學習方法是從幾個基本示例開始。
回到咱們上一個例子,咱們執行這樣的查詢:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } '
查詢部分告訴咱們查詢定義是什麼,match_all部分只是咱們想要運行的查詢類型。這裏match_all查詢只是在指定索引中搜索全部文檔。
除了查詢參數外,咱們還能夠傳遞其餘參數來影響搜索結果。在上面部分的例子中,咱們傳的是sort參數,這裏咱們傳size:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "size": 1 } '
注意:若是size沒有指定,則默認是10
下面的例子執行match_all,並返回第10到19條文檔:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "from": 10, "size": 10 } '
from參數(從0開始)指定從哪一個文檔索引開始,而且size參數指定從from開始返回多少條。這個特性在分頁查詢時很是有用。
注意:若是沒有指定from,則默認從0開始
這個示例執行match_all,並按照賬戶餘額降序對結果進行排序,並返回前10個(默認大小)文檔。
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } } } '
繼續學習查詢DSL。首先,讓咱們看一下返回的文檔字段。默認狀況下,會返回完整的JSON文檔(PS:也就是返回全部字段)。這被成爲source(hits._source)
若是咱們不但願返回整個源文檔,咱們能夠從源文檔中只請求幾個字段來返回。
下面的例子展現了只返回文檔中的兩個字段:account_number 和 balance字段
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "_source": ["account_number", "balance"] } '
(畫外音:至關於SELECT account_number, balance FROM bank)
如今讓咱們繼續查詢部分。之前,咱們已經看到了如何使用match_all查詢匹配全部文檔。如今讓咱們引入一個名爲match query的新查詢,它能夠被看做是基本的字段搜索查詢(即針對特定字段或字段集進行的搜索)。
下面的例子返回account_number爲20的文檔
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match": { "account_number": 20 } } } '
(畫外音:至關於SELECT * FROM bank WHERE account_number = 20)
下面的例子返回address中包含"mill"的帳戶:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match": { "address": "mill" } } } '
(畫外音:至關於SELECT * FROM bank WHERE address LIKE '%mill%')
下面的例子返回address中包含"mill"或者"lane"的帳戶:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match": { "address": "mill lane" } } } '
(畫外音:至關於SELECT * FROM bank WHERE address LIKE '%mill' OR address LIKE '%lane%')
讓咱們來引入bool查詢,bool查詢容許咱們使用布爾邏輯將較小的查詢組合成較大的查詢。
下面的例子將兩個match查詢組合在一塊兒,返回address中包含"mill"和"lane"的帳戶:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } } '
(畫外音:至關於SELECT * FROM bank WHERE address LIKE '%mill%lane%')
上面是bool must查詢,下面這個是bool shoud查詢:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } } '
(畫外音:must至關於and,shoud至關於or,must_not至關於!)
(畫外音:邏輯運算符:與/或/非,and/or/not,在這裏就是must/should/must_not)
咱們能夠在bool查詢中同時組合must、should和must_not子句。此外,咱們能夠在任何bool子句中編寫bool查詢,以模擬任何複雜的多級布爾邏輯。
下面的例子是一個綜合應用:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } } '
(畫外音:至關於SELECT * FROM bank WHERE age LIKE '%40%' AND state NOT LIKE '%ID%')
分數是一個數值,它是文檔與咱們指定的搜索查詢匹配程度的相對度量(PS:類似度)。分數越高,文檔越相關,分數越低,文檔越不相關。
可是查詢並不老是須要產生分數,特別是當它們僅用於「過濾」文檔集時。Elasticsearch檢測到這些狀況並自動優化查詢執行,以便不計算無用的分數。
咱們在前一節中介紹的bool查詢還支持filter子句,該子句容許使用查詢來限制將由其餘子句匹配的文檔,而不改變計算分數的方式。
做爲一個例子,讓咱們引入range查詢,它容許咱們經過一系列值篩選文檔。這一般用於數字或日期過濾。
下面這個例子用一個布爾查詢返回全部餘額在20000到30000之間(包括30000,BETWEEN...AND...是一個閉區間)的帳戶。換句話說,咱們想要找到餘額大於等於20000而且小於等等30000的帳戶。
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } } '
(畫外音:至關於SQL中的彙集函數,好比分組、求和、求平均數之類的)
首先,這個示例按state對全部賬戶進行分組,而後按照count數降序(默認)返回前10條(默認):
(畫外音:至關於按state分組,而後count(*),每一個組中按照COUNT(*)數取 top 10)
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" } } } } '
在SQL中,上面的彙集操做相似於:
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;
響應:
{ "took":50, "timed_out":false, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":1000, "max_score":0, "hits":[ ] }, "aggregations":{ "group_by_state":{ "doc_count_error_upper_bound":20, "sum_other_doc_count":770, "buckets":[ { "key":"ID", "doc_count":27 }, { "key":"TX", "doc_count":27 }, { "key":"AL", "doc_count":25 }, { "key":"MD", "doc_count":25 }, { "key":"TN", "doc_count":23 }, { "key":"MA", "doc_count":21 }, { "key":"NC", "doc_count":21 }, { "key":"ND", "doc_count":21 }, { "key":"ME", "doc_count":20 }, { "key":"MO", "doc_count":20 } ] } } }
注意,咱們將size=0設置爲不顯示搜索結果,由於咱們只想看到響應中的聚合結果。
接下來的例子跟上一個相似,按照state分組,而後取balance的平均值
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } } '
在SQL中,至關於:
SELECT state, COUNT(*), AVG(balance) FROM bank GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;
下面這個例子展現了咱們如何根據年齡段(20-29歲,30-39歲,40-49歲)來分組,而後根據性別分組,最後獲得平均帳戶餘額,每一個年齡等級,每一個性別:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "size": 0, "aggs": { "group_by_age": { "range": { "field": "age", "ranges": [ { "from": 20, "to": 30 }, { "from": 30, "to": 40 }, { "from": 40, "to": 50 } ] }, "aggs": { "group_by_gender": { "terms": { "field": "gender.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } } } } '
先寫到這裏吧!!!
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html
發現有一本書叫《Elasticsearch: 權威指南》