到目前爲止,已經瞭解了基本知識,如今咱們嘗試用更逼真的數據集,這兒已經準備好了一份虛構的JSON,關於客戶銀行帳戶信息的。每一個文檔的結構以下:html
{ "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" }
出於好奇,我從www.json-generator.com/生成了這些數據,請忽略數據的實際值和語義,由於這些都是隨機生成的。git
能夠從這裏下載示例數據集(accounts.json),解壓到當前目錄,而後用如下方式把它加載到集羣中github
curl -H "Content-Type: application/json" -XPOST 'localhost:9200/bank/account/_bulk?pretty&refresh' --data-binary "@accounts.json" curl 'localhost:9200/_cat/indices?v'
返回內容以下:sql
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open .kibana XYZPR5XGQGWj8YlyZ1et_w 1 1 1 0 3.1kb 3.1kb yellow open bank uoTQIb3GSDOH08CmsIy66A 5 1 999 0 639.5kb 639.5kb
這意味着咱們已經成功批量索引999個文檔到bank索引下(類型爲account )。json
注意,上面的操做不能在kibana中執行,須要使用curlapi
具體操做是,把下載的json文檔放在和curl.exe相同的目錄,而後打開命令提示符定位到curl.exe所在目錄,而後粘貼如下命令(個人curl版本是7.53.1,須要改爲下面的方式才能執行成功),回車便可數組
curl -H "Content-Type: application/json" -XPOST localhost:9200/bank/account/_bulk?pretty --data-binary "@accounts.json"
運行查詢有兩種方式,一是經過 REST request URI 方式發送查詢參數,二是經過 REST request body 。方式二更爲靈活,可使用可讀性好的JSON 格式定義你的查詢條件,下面咱們針對方式一舉個例子,之後的教程都使用方式二。服務器
REST API的查詢條件放在_search以後,如下例子返回 bank 索引中的全部文檔:網絡
GET /bank/_search?q=*&sort=account_number:asc&pretty
bank 表示查詢bank索引中的文檔, _search 後面跟的是查詢條件,q=* 參數指示 Elasticsearch 匹配索引中的全部文檔。 sort=account_number:asc 參數指示使用 account_number 對結果進行升序排序。 pretty 參數告訴 Elasticsearch 返回漂亮的JSON結果。
返回部份內容以下:app
{ "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 執行查詢的時間(以毫秒爲單位)timed_out
- 告訴咱們查詢是否超時_shards
- 告訴咱們查詢了多少個分片,以及查詢成功/失敗的分片數量hits
- 查詢結果hits.total
- 符合咱們查詢條件的文檔總數hits.hits
- 實際查詢結果數組(默認爲前10個文檔)hits.sort
- 對結果進行排序的鍵(若是沒提供,則默認使用_score進行排序)hits._score
和max_score
-如今先忽略這些字段使用方式二執行上面查詢以下
GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] }
不一樣點是咱們用json格式的請求體代替了_search api uri中的q=*參數。咱們將會在後面的內容討論json格式的查詢。
Elasticsearch t提供了一種 JSON-style 的特定領域語言用來執行查詢,稱爲 Query DSL,該查詢語言十分全面,初看可能以爲有點嚇人。事實上,學習它的最好方式就是從幾個基本的例子開始。回到上一個例子,咱們執行了這個查詢:
GET /bank/_search { "query": { "match_all": {} } }
上面的 query 部分告訴咱們查詢定義是什麼, match_all 部分僅僅是咱們想運行的查詢的類型,也就是查詢指定索引下的全部文檔。
除了查詢參數之外,也能夠經過其餘參數影響查詢結果。好比前面的 sort 指定排序字段,下面經過 size 指定返回結果數
GET /bank/_search { "query": { "match_all": {} }, "size": 1 }
下面的例子匹配全部,而且返回第11到20之間的文檔
GET /bank/_search { "query": { "match_all": {} }, "from": 10, "size": 10 }
from參數(最小值是0,不是1)指定返回文檔的起始文檔的索引, size 參數指定一共返回多少個文檔。這個特性對實現分頁很是有用。若是 from 沒有指定,默認值是0。
下面的例子匹配全部,而且經過 balance 字段對結果進行降序排序,返回前10條(默認 size )文檔。
GET /bank/_search { "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } } }
接下來咱們進一步探討Query DSL。首先看一下返回的文檔字段。默認狀況下,完整的JSON文檔做爲全部搜索的一部分返回。
默認狀況下,完整的JSON文檔做爲全部搜索的一部分返回。文檔原始內容被稱爲源(查詢結果中的_source字段
)。若是不但願返回整個源文檔,也能夠請求僅幾個字段被返回。
如下示例顯示如何返回兩個字段(_source內
), account_number 和 balance :
GET /bank/_search { "query": { "match_all": {} }, "_source": ["account_number", "balance"], "size": 1 }
返回內容以下:
{ "took": 3, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 999, "max_score": 1, "hits": [ { "_index": "bank", "_type": "account", "_id": "25", "_score": 1, "_source": { "account_number": 25, "balance": 40540 } } ] } }
以上的例子僅僅減小了 _source 裏的字段,返回的字段 account_number 和 balance 仍然包含在 _source 中
若是你以前有SQL背景,上述在概念上與SQL SELECT FROM
字段列表有些類似。
如今來看看查詢部分。經過前面的示例,咱們已經學會了如何使用 match_all 查詢來匹配全部文檔。如今介紹一個名爲match
查詢的新查詢,能夠將其視爲基本的字段搜索查詢(即針對特定字段或一組字段進行搜索)。
如下示例返回的 account_number 爲20:
GET /bank/_search { "query": { "match": { "account_number": 20 } } }
返回結果:
{ "took": 15, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 1, "hits": [ { "_index": "bank", "_type": "account", "_id": "20", "_score": 1, "_source": { "account_number": 20, "balance": 16418, "firstname": "Elinor", "lastname": "Ratliff", "age": 36, "gender": "M", "address": "282 Kings Place", "employer": "Scentric", "email": "elinorratliff@scentric.com", "city": "Ribera", "state": "WA" } } ] } }
如下實例返回 address 中包含"mill"的全部帳戶:
GET /bank/_search { "query": { "match": { "address": "mill" } } }
如下示例返回address中包含"mill"或者"lane"的全部帳戶:
GET /bank/_search { "query": { "match": { "address": "mill lane" } } }
如下示例是match
(match_phrase
)的一個變體,返回在地址中包含短語"mill lane"的全部賬戶:
GET /bank/_search { "query": { "match_phrase": { "address": "mill lane" } } }
下面介紹bool
(ean) query 。 布爾
查詢容許咱們把多個 match 查詢合併到一個查詢中。
如下示例由兩個 match 查詢組成,返回 address 中既包含"mill" 又包含"lane" 的全部帳戶:
GET /bank/_search { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
在上面的示例中, bool must 裏面的全部查詢條件必須都爲真時纔會被匹配。
相比之下,下面的示例由兩個match
查詢組成,並返回在地址中包含"mill"或"lane"的全部賬戶:
GET /bank/_search { "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
在上面的例子中, bool should 子句指定了一個查詢列表,只要其中一個查詢爲真,文檔就會被匹配。
如下示例由兩個match
查詢組成,並返回在地址中既不包含"mill"也不包含"lane"的全部賬戶:
GET /bank/_search { "query": { "bool": { "must_not": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }
在上面的例子中,bool must_not 子句指定一個查詢列表,只有查詢列表中的條件都爲假的時候纔會被匹配。
也能夠把 must,should,must_not 同時組合到bool
子句。此外,咱們也能夠組合bool
到任何一個bool
子句中,實現複雜的多層bool
子句嵌套邏輯。
下面的例子返回全部年齡是40歲但不居住在ID(Idaho)的帳戶:
GET /bank/_search { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }
前面咱們跳過了一點細節,文檔得分(也就是在搜索結果中的 _score 字段)。分數是一個數值,它是文檔與咱們指定的搜索查詢匹配的相對度量。分數越高,文檔越相關,分數越低,文檔的相關性越低。但查詢並不老是須要產生分數,特別是當它們僅用於"過濾"文檔集時。 Elasticsearch 會檢測這些狀況,並自動優化查詢執行,以避免計算無用的分數。
bool
查詢支持filter子句,它容許你使用一個查詢語句去限制其它子句的匹配結果,同時不會計算文檔的得分。例如,咱們來介紹一下
range
query, 它容許咱們經過一個範圍值去過濾文檔。一般用於數字或日期過濾。
如下示例使用布爾查詢返回餘額在20000到30000之間(包括端值)的全部賬戶。換句話說,咱們想找到餘額大於或等於20000且小於等於30000的帳戶。
GET /bank/_search { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } }
仔細分析上面的例子,bool
查詢包含了一個match_all
查詢(查詢部分)和一個range
查詢(過濾部分)。咱們也能夠用任何其它的查詢語句代替查詢和過濾部分的語句。對於上面的例子,由於全部文檔都是指定範圍以內的,他們從某種意義上來講是等價的(equally),即他們的相關度都是同樣的(filter子句查詢,不會改變得分)。
除了 match_all
,match
,bool
,range
查詢,還有不少種類的查詢,但咱們不在這裏一一介紹。從如今開始,咱們對查詢已經有一個基礎的瞭解,把學到的知識應用到其餘查詢類型應該也沒什麼難度。
聚合提供從數據中分組和提取統計信息的功能。理解聚合的最簡單的方法是將其大體等同於SQL GROUP BY和SQL聚合函數。在 Elasticsearch 中,能夠返回匹配搜索的同時返回聚合結果,在一個響應中將全部匹配的結果和聚合結果同時返回。這是很是強大和高效的,能夠下降網絡請求的次數。
如下示例經過state
字段進行分組,並按照count 降序排序,返回前10(默認值)條數據:
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" } } } }
在SQL中,上述聚合在概念上相似於:
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC
返回內容(僅部分)以下:
{ "took": 50, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 999, "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": "MO", "doc_count": 20 }, { "key": "AK", "doc_count": 19 } ] } } }
能夠看到,有27個帳戶居住在ID(Idaho),27個帳戶居住在TX(Texas),25個帳戶居住在AL(Alabama)等等。
注意,設置size=0
是爲了避免顯示搜索結果,由於咱們僅僅想看返回的聚合結果。
基於上述例子,下面的例子除了分組還會計算每一個州的帳戶的平均餘額:
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
返回內容(僅部分)以下:
{ "took": 32, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 999, "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, "average_balance": { "value": 24368.777777777777 } }, { "key": "TX", "doc_count": 27, "average_balance": { "value": 27462.925925925927 } }, { "key": "AL", "doc_count": 25, "average_balance": { "value": 25739.56 } }, { "key": "MD", "doc_count": 25, "average_balance": { "value": 24963.52 } }, { "key": "TN", "doc_count": 23, "average_balance": { "value": 29796.782608695652 } }, { "key": "MA", "doc_count": 21, "average_balance": { "value": 29726.47619047619 } }, { "key": "NC", "doc_count": 21, "average_balance": { "value": 26785.428571428572 } }, { "key": "ND", "doc_count": 21, "average_balance": { "value": 26303.333333333332 } }, { "key": "MO", "doc_count": 20, "average_balance": { "value": 24151.8 } }, { "key": "AK", "doc_count": 19, "average_balance": { "value": 24088.63157894737 } } ] } } }
注意咱們是如何把average_balance聚合嵌入到group_by_state聚合中的。在全部的聚合中這是一種廣泛的模式。你能夠按你的需求隨意的在聚合中嵌套聚合子句,彙總你的數據。
基於上面的例子,如下示例加入了按每一個州的帳戶平均餘額降序排序:
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword", "order": { "average_balance": "desc" } }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
如下示例演示瞭如何按年齡段(20-29歲,30-39歲和40-49歲),而後按性別分組,而後最終獲得每一個年齡段的男女平均帳戶餘額:
GET /bank/_search { "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" } } } } } } } }
返回結果以下:
{ "took": 21, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 999, "max_score": 0, "hits": [] }, "aggregations": { "group_by_age": { "buckets": [ { "key": "20.0-30.0", "from": 20, "to": 30, "doc_count": 450, "group_by_gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "M", "doc_count": 231, "average_balance": { "value": 27400.982683982686 } }, { "key": "F", "doc_count": 219, "average_balance": { "value": 25341.260273972603 } } ] } }, { "key": "30.0-40.0", "from": 30, "to": 40, "doc_count": 504, "group_by_gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "F", "doc_count": 253, "average_balance": { "value": 25670.869565217392 } }, { "key": "M", "doc_count": 251, "average_balance": { "value": 24288.239043824702 } } ] } }, { "key": "40.0-50.0", "from": 40, "to": 50, "doc_count": 45, "group_by_gender": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "M", "doc_count": 24, "average_balance": { "value": 26474.958333333332 } }, { "key": "F", "doc_count": 21, "average_balance": { "value": 27992.571428571428 } } ] } } ] } } }
還有許多其餘聚合功能,將再也不詳細介紹。若是您想進一步試驗,聚合參考指南是一個很好的起點。
elasticsearch 是一個既簡單又複雜的產品。目前爲止,咱們已經學瞭如何使用REST API以及 elasticsearch 的基本概念和特性。但願這個教程可讓你很好的理解 elasticsearch ,更重要的是,激勵你繼續學習後續教程要介紹的強大特性。
官方文檔
https://www.elastic.co/guide/en/elasticsearch/reference/current/_exploring_your_data.html
參考文檔
https://github.com/13428282016/elasticsearch-CN/wiki/es-gettting-started