Elasticsearch 是一款穩定高效的分佈式搜索和分析引擎,它的底層基於 Lucene,並提供了友好的 RESTful API 來對數據進行操做,還有比較重要的一點是, Elasticsearch 開箱便可用,上手也比較容易。html
目前 Elasticsearch 在搭建企業級搜索(如日誌搜索、商品搜索等)平臺中很普遍,官網也提供了很多案例,好比:java
GitHub 使用 Elasticsearch 檢索超過 800 萬的代碼庫node
eBay 使用 Elasticsearch 搜索海量的商品數據git
Netflix 使用 Elasticsearch 來實現高效的消息傳遞系統數據庫
本文主要介紹 Elasticsearch 的基本概念及入門使用。apache
<!-- more -->json
在安裝 Elasticsearch 以前,請確保你的計算機已經安裝了 Java。目前 Elasticsearch 的最新版是 5.2,須要安裝 Java 8,若是你用的是老版本的 Elasticsearch,如 2.x 版,可用 Java 7,但仍是推薦使用 Java 8。數組
可使用以下的命令檢查 Java 的版本:瀏覽器
$ java -version
接着,咱們能夠從這裏下載最新版本的 Elasticsearch,也可以使用 wget 下載,以下:app
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.2.tar.gz
Windows 用戶也能夠下載 .zip
格式的安裝包。
下載完後進行解壓:
$ tar -zxvf elasticsearch-5.2.2.tar.gz
首先,咱們進入到剛剛解壓出來的目錄中:
$ cd elasticsearch-5.2.2
接着,使用以下命令啓動 Elasticsearch:
$ bin/elasticsearch
此時,若是正常的話,你能夠在終端看到相似以下的輸出:
[2017-03-04T23:25:09,961][INFO ][o.e.n.Node ] [] initializing ... [2017-03-04T23:25:10,073][INFO ][o.e.e.NodeEnvironment ] [yO11WLM] using [1] data paths, mounts [[/ (/dev/disk0s2)]], net usable_space [141.1gb], net total_space [232.9gb], spins? [unknown], types [hfs] [2017-03-04T23:25:10,074][INFO ][o.e.e.NodeEnvironment ] [yO11WLM] heap size [1.9gb], compressed ordinary object pointers [true] [2017-03-04T23:25:10,095][INFO ][o.e.n.Node ] node name [yO11WLM] derived from node ID [yO11WLMOQDuAOpZbYZYjzw]; set [node.name] to override [2017-03-04T23:25:10,100][INFO ][o.e.n.Node ] version[5.2.2], pid[7607], build[db0d481/2017-02-09T22:05:32.386Z], OS[Mac OS X/10.11.5/x86_64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_102/25.102-b14] [2017-03-04T23:25:11,363][INFO ][o.e.p.PluginsService ] [yO11WLM] loaded module [aggs-matrix-stats] ...
上面的命令是在前臺運行的,若是想在後臺以守護進程模式運行,能夠加 -d
參數。
Elasticsearch 啓動後,也啓動了兩個端口 9200 和 9300:
9200 端口:HTTP RESTful 接口的通信端口
9300 端口:TCP 通信端口,用於集羣間節點通訊和與 Java 客戶端通訊的端口
如今,讓咱們作一些測試。在瀏覽器訪問連接 http://localhost:9200/ ,或使用 curl 命令:
$ curl 'http://localhost:9200/?pretty'
咱們能夠看到相似以下的輸出:
{ "name" : "yO11WLM", "cluster_name" : "elasticsearch", "cluster_uuid" : "yC8BGwzlSnu_zGbKL918Xg", "version" : { "number" : "5.2.1", "build_hash" : "db0d481", "build_date" : "2017-02-09T22:05:32.386Z", "build_snapshot" : false, "lucene_version" : "6.4.1" }, "tagline" : "You Know, for Search" }
在進一步使用 Elasticsearch 以前,讓咱們先了解幾個關鍵概念。
在邏輯層面:
Index (索引):這裏的 Index 是名詞,一個 Index 就像是傳統關係數據庫的 Database,它是 Elasticsearch 用來存儲數據的邏輯區域
Document (文檔):Elasticsearch 使用 JSON 文檔來表示一個對象,就像是關係數據庫中一個 Table 中的一行數據
Type (類型):文檔歸屬於一種 Type,就像是關係數據庫中的一個 Table
Field (字段):每一個文檔包含多個字段,相似關係數據庫中一個 Table 的列
咱們用一個表格來作類比,以下:
Elasticsearch | MySQL |
---|---|
Index | Database |
Type | Table |
Document | Row |
Field | Column |
在物理層面:
Node (節點):node 是一個運行着的 Elasticsearch 實例,一個 node 就是一個單獨的 server
Cluster (集羣):cluster 是多個 node 的集合
Shard (分片):數據分片,一個 index 可能會存在於多個 shard
接下來,咱們看看如何創建索引、建立文檔等,就比如在 MySQL 中進行諸如建立數據庫,插入數據等操做。
下面,咱們將建立一個存儲電影信息的 Document:
Index 的名稱爲 movie
Type 爲 adventure
Document 有兩個字段:name 和 actors
咱們使用 Elasticsearch 提供的 RESTful API 來執行上述操做,如圖所示:
用 url 表示一個資源,好比 /movie/adventure/1
就表示一個 index
爲 movie,type
爲 adventure,id
爲 1 的 document
用 http 方法操做資源,如使用 GET 獲取資源,使用 POST、PUT 新增或更新資源,使用 DELETE 刪除資源等
咱們可使用 curl 命令來執行上述操做:
$ curl -i -X PUT "localhost:9200/movie/adventure/1" -d '{"name": "Life of Pi", "actors": ["Suraj", "Irrfan"]}'
不過,本文推薦使用 httpie,相似 curl,但比 curl 更好用,將上面的命令換成 httpie,以下:
$ http put :9200/movie/adventure/1 name="Life of Pi" actors:='["Suraj", "Irrfan"]'
上面的命令結果以下:
HTTP/1.1 201 Created Location: /movie/adventure/1 content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 1, "created": true, "result": "created" }
能夠看到,咱們已經成功建立了一個 _index
爲 movie,_type
爲 adventure,_id
爲 1 的文檔。
咱們經過 GET 請求來查看這個文檔的信息:
$ http :9200/movie/adventure/1
結果以下:
HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_source": { "actors": [ "Suraj", "Irrfan" ], "name": "Life of Pi" }, "_type": "adventure", "_version": 1, "found": true }
能夠看到,原始的文檔數據存在了 _source
字段中。
若是咱們的數據沒有 id,也可讓 Elasticsearch 自動爲咱們生成,此時要使用 POST 請求,形式以下:
POST /movie/adventure/ { "name": "Life of Pi" }
當咱們使用 PUT 方法指明文檔的 _index
, _type
和 _id
時,若是 _id
已存在,則新文檔會替換舊文檔,此時文檔的 _version
會增長 1,而且 _created
字段爲 false。好比:
$ http put :9200/movie/adventure/1 name="Life of Pi"
結果以下:
HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 2, "created": false, "result": "updated" }
使用 GET 請求查看新文檔的數據:
$ http :9200/movie/adventure/1
結果以下:
HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_source": { "name": "Life of Pi" }, "_type": "adventure", "_version": 2, "found": true }
能夠看到,actors 這個字段已經不存在了,文檔的 _version
變成了 2。
所以,爲了不在誤操做的狀況下,原文檔被替換,咱們可使用 _create
這個 API,表示只在文檔不存在的狀況下才建立新文檔(返回 201 Created),若是文檔存在則不作任何操做(返回 409 Conflict),命令以下:
$ http put :9200/movie/adventure/1/_create name="Life of Pi"
因爲文檔 id 存在,會返回 409 Conflict。
在有些狀況下,咱們只想更新文檔的局部,而不是整個文檔,這時咱們可使用 _update
這個 API。
如今,待更新的文檔信息以下:
{ "_id": "1", "_index": "movie", "_source": { "name": "Life of Pi" }, "_type": "adventure", "_version": 2, "found": true }
最簡單的 update 請求接受一個局部文檔參數 doc
,它會合併到現有文檔中:將對象合併在一塊兒,存在的標量字段被覆蓋,新字段被添加。
形式以下:
POST /movie/adventure/1/_update { "doc": { "name": "life of pi" } }
因爲有嵌套字段,咱們能夠這樣使用 http(這裏須要注意使用 POST 方法):
$ echo '{"doc": {"actors": ["Suraj", "Irrfan"]}}' | http post :9200/movie/adventure/1/_update
上面的命令中,咱們添加了一個新的字段:actors,結果以下:
HTTP/1.1 200 OK content-encoding: gzip content-type: application/json; charset=UTF-8 transfer-encoding: chunked { "_id": "1", "_index": "movie", "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_type": "adventure", "_version": 3, "result": "updated" }
能夠看到,_version 增長了 1,result 的結果是 updated。
要檢索某個文檔很簡單,咱們只需使用 GET 請求並指出文檔的 index, type, id 就能夠了,好比:
$ http :9200/movie/adventure/1/
響應內容會包含文檔的元信息,文檔的原始數據存在 _source
字段中。
咱們也能夠直接檢索出文檔的 _source
字段,以下:
$ http :9200/movie/adventure/1/_source
咱們可使用 _search
這個 API 檢索出全部的文檔,命令以下:
$ http :9200/movie/adventure/_search
返回結果以下:
{ "_shards": { "failed": 0, "successful": 5, "total": 5 }, "hits": { "hits": [ { "_id": "1", "_index": "movie", "_score": 1.0, "_source": { "actors": [ "Suraj", "Irrfan" ], "name": "Life of Pi" }, "_type": "adventure" } ], "max_score": 1.0, "total": 1 }, "timed_out": false, "took": 299 }
能夠看到,hits
這個 object 包含了 hits 數組,total 等字段,其中,hits 數組包含了全部的文檔,這裏只有一個文檔,total 代表了文檔的數量,默認狀況下會返回前 10 個結果。咱們也能夠設定 From/Size
參數來獲取某一範圍的文檔,可參考這裏,好比:
$ http :9200/movie/adventure/_search?from=1&size=5
當不指定 from 和 size 時,會使用默認值,其中 from 的默認值是 0,size 的默認值是 10。
有時候,咱們只需檢索文檔的個別字段,這時可使用 _source
參數,多個字段可使用逗號分隔,以下所示:
$ http :9200/movie/adventure/1?_source=name $ http :9200/movie/adventure/1?_source=name,actors
query string 搜索以 q=field:value
的形式進行查詢,好比查詢 name 字段含有 life 的電影:
$ http :9200/movie/adventure/_search?q=name:life
上面的 query string 搜索比較輕量級,只適用於簡單的場合。Elasticsearch 提供了更爲強大的 DSL(Domain Specific Language)查詢語言,適用於複雜的搜索場景,好比全文搜索。咱們能夠將上面的 query string 搜索轉換爲 DSL 搜索,以下:
GET /movie/adventure/_search { "query" : { "match" : { "name" : "life" } } }
若是使用 httpie,能夠這樣:
$ echo '{"query": {"match": {"name": "life"}}}' | http get :9200/movie/adventure/_search
若是使用 curl,能夠這樣:
$ curl -X GET "127.0.0.1:9200/movie/adventure/_search" -d '{"query": {"match": {"name": "life"}}}'
使用 HEAD 方法查看文檔是否存在:
$ http head :9200/movie/adventure/1
若是文檔存在則返回 200,不然返回 404。
使用 DELETE 方法刪除文檔:
$ http delete :9200/movie/adventure/1
Elasticsearch 經過簡單的 RESTful API 來隱藏 Lucene 的複雜性,從而讓全文搜索變得簡單
在建立文檔時,咱們能夠用 POST 方法指定將文檔添加到某個 _index/_type
下,來讓 Elasticsearch自動生成惟一的 _id
;而用 PUT 方法指定將文檔的 _index/_type/_id
本文由 funhacks 發表於我的博客,採用 Creative Commons BY-NC-ND 4.0(自由轉載-保持署名-非商用-禁止演繹)協議發佈。
非商業轉載請註明做者及出處。商業轉載請聯繫做者本人。
本文標題爲: Elasticsearch 簡介
本文連接爲: http://funhacks.net/2017/03/2...