Elasticsearch 數據搜索篇·【入門級乾貨】

ES即簡單又複雜,你能夠快速的實現全文檢索,又須要瞭解複雜的REST API。本篇就經過一些簡單的搜索命令,幫助你理解ES的相關應用。雖然不能讓你理解ES的原理設計,可是能夠幫助你理解ES,探尋更多的特性。html

其餘相關的內容參考:Elasticsearch官方文檔翻譯數據庫

樣例數據

爲了更好的使用和理解ES,沒有點樣例數據仍是很差模擬的。這裏提供了一份官網上的數據,accounts.json。若是須要的話,也能夠去這個網址玩玩,它能夠幫助你自定義寫隨機的JSON數據json

首先開啓你的ES,而後執行下面的命令,windows下須要本身安裝curl、也可使用cygwin模擬curl命令:windows

curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary  @accounts.json

注意:網絡

1 須要在accounts.json所在的目錄運行curl命令。dom

2 localhost:9200是ES得訪問地址和端口curl

3 bank是索引的名稱函數

4 account是類型的名稱搜索引擎

5 索引和類型的名稱在文件中若是有定義,能夠省略;若是沒有則必需要指定url

6 _bulk是rest得命令,能夠批量執行多個操做(操做是在json文件中定義的,原理能夠參考以前的翻譯)

7 pretty是將返回的信息以可讀的JSON形式返回。

執行完上述的命令後,能夠經過下面的命令查詢:

curl 'localhost:9200/_cat/indices?v' health index pri rep docs.count docs.deleted store.size pri.store.size yellow bank 5   1       1000            0    424.4kb        424.4kb

搜索API

ES提供了兩種搜索的方式:請求參數方式請求體方式

請求參數方式

curl 'localhost:9200/bank/_search?q=*&pretty'

其中bank是查詢的索引名稱,q後面跟着搜索的條件:q=*表示查詢全部的內容

請求體方式(推薦這種方式)

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_all": {} } }'

這種方式會把查詢的內容放入body中,會形成必定的開銷,可是易於理解。在平時的練習中,推薦這種方式。

 

返回的內容

{ "took" : 26, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1000, "max_score" : 1.0, "hits" : [ { "_index" : "bank", "_type" : "account", "_id" : "1", "_score" : 1.0, "_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"} }, { "_index" : "bank", "_type" : "account", "_id" : "6", "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"} }, { "_index" : "bank", "_type" : "account", "_id" : "13",

返回的內容大體能夠以下講解:

took:是查詢花費的時間,毫秒單位

time_out:標識查詢是否超時

_shards:描述了查詢分片的信息,查詢了多少個分片、成功的分片數量、失敗的分片數量等

hits:搜索的結果,total是所有的知足的文檔數目,hits是返回的實際數目(默認是10)

_score是文檔的分數信息,與排名相關度有關,參考各大搜索引擎的搜索結果,就容易理解。 

因爲ES是一次性返回全部的數據,所以理解返回的內容是很必要的。它不像傳統的SQL是先返回數據的一個子集,再經過數據庫端的遊標不斷的返回數據(因爲對傳統的數據庫理解的不深,這裏有錯還望指正)。

查詢語言DSL

ES支持一種JSON格式的查詢,叫作DSL,domain specific language。這門語言剛開始比較難理解,所以經過幾個簡單的例子開始:

下面的命令,能夠搜索所有的文檔:

{ "query": { "match_all": {} } }

query定義了查詢,match_all聲明瞭查詢的類型。還有其餘的參數能夠控制返回的結果:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_all": {} }, "size": 1 }'

上面的命令返回了全部文檔數據中的第一條文檔。若是size不指定,那麼默認返回10條。

 

下面的命令請求了第10-20的文檔。

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_all": {} }, "from": 10, "size": 10 }'

 

下面的命令指定了文檔返回的排序方式:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } } }'

 

執行搜索

上面瞭解了基本的搜索語句,下面就開始深刻一些經常使用的DSL了。

以前的返回數據都是返回文檔的全部內容,這種對於網絡的開銷確定是有影響的,下面的例子就指定了返回特定的字段:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_all": {} }, "_source": ["account_number", "balance"] }'

再回到query,以前的查詢都是查詢全部的文檔,並不能稱之爲搜索引擎。下面就經過match方式查詢特定字段的特定內容,好比查詢餘額爲20的帳戶信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match": { "account_number": 20 } } }'

查詢地址爲mill的信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match": { "address": "mill" } } }'

查詢地址爲mill或者lane的信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match": { "address": "mill lane" } } }'

若是咱們想要返回同時包含mill和lane的,能夠經過match_phrase查詢:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "match_phrase": { "address": "mill lane" } } }'

ES提供了bool查詢,能夠把不少小的查詢組成一個更爲複雜的查詢,好比查詢同時包含mill和lane的文檔:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }'

修改bool參數,能夠改成查詢包含mill或者lane的文檔:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }'

也能夠改寫爲must_not,排除包含mill和lane的文檔:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "must_not": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }'

bool查詢能夠同時使用must, should, must_not組成一個複雜的查詢:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }'

過濾查詢

以前說過score字段指定了文檔的分數,使用查詢會計算文檔的分數,最後經過分數肯定哪些文檔更相關,返回哪些文檔。

有的時候咱們可能對分數不感興趣,就可使用filter進行過濾,它不會去計算分值,所以效率也就更高一些。

filter過濾能夠嵌套在bool查詢內部使用,好比想要查詢在2000-3000範圍內的全部文檔,能夠執行下面的命令:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } }'

ES除了上面介紹過的範圍查詢range、match_all、match、bool、filter還有不少其餘的查詢方式,這裏就先不一一說明了。

聚合

聚合提供了用戶進行分組和數理統計的能力,能夠把聚合理解成SQL中的GROUP BY和分組函數。在ES中,你能夠在一次搜索查詢的時間內,即完成搜索操做也完成聚合操做,這樣就下降了屢次使用REST API形成的網絡開銷。

下面就是經過terms聚合的簡單樣例:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state" } } } }'

它相似於SQL中的下面的語句:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC

返回的數據:

"hits" : { "total" : 1000, "max_score" : 0.0, "hits" : [ ] }, "aggregations" : { "group_by_state" : { "buckets" : [ { "key" : "al", "doc_count" : 21 }, { "key" : "tx", "doc_count" : 17 }, { "key" : "id", "doc_count" : 15 }, { "key" : "ma", "doc_count" : 15 }, { "key" : "md", "doc_count" : 15 }, { "key" : "pa", "doc_count" : 15 }, { "key" : "dc", "doc_count" : 14 }, { "key" : "me", "doc_count" : 14 }, { "key" : "mo", "doc_count" : 14 }, { "key" : "nd", "doc_count" : 14 } ] } } }

因爲size設置爲0,它並無返回文檔的信息,只是返回了聚合的結果。

好比統計不一樣帳戶狀態下的平均餘額:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }'

聚合支持嵌套,舉個例子,先按範圍分組,在統計不一樣性別的帳戶餘額:

curl -XPOST 'localhost:9200/bank/_search?pretty' -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" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } } } }'

聚合能夠實現不少複雜的功能,並且ES也提供了不少複雜的聚合,這裏做爲引導篇,也不過多介紹了。

 

對於基本的數據搜索大體就是上面講述的樣子,熟悉了一些經常使用的API,入門仍是很簡單的,卻是要熟練使用ES,仍是須要掌握各類搜索查詢的命令,以及ES內部的原理。

相關文章
相關標籤/搜索