介紹
elasticsearch是一個高效的、可擴充的全文檢索搜尋引擎 基本概念 Near Realtime(NRT): es是一個接近即時查詢平台,意味從儲存一條資料到可以索引到資料時差很小,通常在1s內 Cluster: es是一個分布式、可擴充的平台, 可由一個或多個伺服器通過定義的cluster.name(預設為elasticsearch)標識共建同一個叢集 Node: 通常一台伺服器上部署一台es node,作為叢集的一部分,用於資料的儲存和提供搜尋功能,在一個叢集中節點通過node.name區分,預設在node啟動時隨機產生一個的字串做為節點名稱,可配置 Index: 類似於關係型資料庫中的database,用於組織一類功能相似的資料,在一個叢集中可以定義任意個索引,索引的名稱只能由小寫字母組成,在資料索引,更新,搜尋,刪除時作為資料標識的一部分 Type: 類似於關係型資料庫中的table,在Index中可以定義多個Type,原則上一個Type是由相同屬性群組成的資料集合 Document: 類似於關係型資料庫中的record,是資料的最基本存放裝置單元,使用json形式表示,Document在物理上儲存在Index下,但是在邏輯上會分配到具體的Type下 Shards & Replica:
一個Index可能儲存大量的資料(超過單個節點的硬體限制),不管是資料存放區還是資料索引,為解決資料單節點儲存並提高並發,es將每一個Index物理分為多個片,從而水平擴充儲存容量,提高並發(可以同時對個shard進行索引和搜尋)
為防止某個儲存單元出現故障後資料不能索引的情況,es提供將shard進行複製功能,將主shard出現故障後,複製shard替代主shard進行資料索引操作,已此方式實現其高可用性,因為在搜尋時可以使用複製shard,從而提高的資料搜尋的並發性
在Index建立時可以進行分區數量和複製數量的設定,預設建立每個Index設定5個shard和1個Replica,表示該Index由5個邏輯儲存單元進行儲存,每個邏輯儲存單元具有一個複製節點進行備災,注意,shard只能在建立Index時進行設定,shard數量與document分配到哪個shard上儲存有關(通常使用hash(document _id) % shard num計算 document儲存在哪個shard上)
在es將主shard和replic分區在不同的Node上 安裝 elasticsearch使用java語言實現,在使用時必須安裝java虛擬機器(目前es1.6和1.7版本均可選擇1.8版本java) 下載地址 解壓到安裝目錄 C:\Program Files\elasticsearch 運行 cd "C:\Program Files\elasticsearch\bin" && elasticsearch.bat 安裝到服務 service install elasticsearch 啟動服務 net start elasticsearch 停止服務 net stop elasticsearch 測試
訪問地址: http://localhost:9200
訪問結果:
12345678910111213
{ status: 200, name: "Smart Alec", cluster_name: "elasticsearch", version: { number: "1.6.0", build_hash: "cdd3ac4dde4f69524ec0a14de3828cb95bbb86d0", build_timestamp: "2015-06-09T13:36:34Z", build_snapshot: false, lucene_version: "4.10.4" }, tagline: "You Know, for Search"} 介面
es對外提供標準RESTAPI介面,使用他進行叢集的所有操作: 叢集、節點、索引的狀態和統計資訊查看 管理叢集、節點、索引和類型 執行CURD操作(建立,更新,讀取,刪除)和索引 執行進階搜尋功能,比如排序,分頁,篩選,彙總,js指令碼執行等
格式:curl -X<REST verb> <Node>:<Port>/<Index>/<Type>/<ID> 使用marvel外掛程式 運行 cd "C:\Program Files\elasticsearch\bin" && plugin -i elasticsearch/marvel/latest 訪問地址 marvel提供sense工具調用es的RESTAPI借口, 訪問地址, 以下操作使用sense或使用linux curl命令列練習 狀態查詢 叢集狀態查詢
輸入: GET _cat/health?v
輸出:
12
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks1442227489 18:44:49 elasticsearch yellow 1 1 50 50 0 0 50 0
說明:
status:表示叢集的健康狀態,值可能為green,yellow,red, green表示主shard和replica(至少一個)正常,yellow表示主shard正常但replica都不正常,red表示有的主shard和replica都有問題
node.total:表示叢集中節點的數量 節點狀態查詢
輸入: GET /_cat/nodes?v
輸出:
12
host ip heap.percent ram.percent load node.role master namesilence 192.168.1.111 30 51 d * Thunderbird
查詢所有索引
輸入: GET /_cat/indices?v
輸出:
123
health status index pri rep docs.count docs.deleted store.size pri.store.sizeyellow open .marvel-2015.09.02 1 1 93564 0 78.4mb 78.4mbyellow open .marvel-2015.09.01 1 1 39581 0 45.9mb 45.9mb
建立索引
輸入: PUT /test1?pretty
輸出:
123
{ "acknowledged" : true}
查詢所有索引:
12
health status index pri rep docs.count docs.deleted store.size pri.store.sizeyellow open test1 5 1 0 0 575b 575b
說明:
health:由於只運行一個節點,replica不能與主shard在同一node中,因此replica不正常,該index的狀態為yellow
index:為索引名稱
pri:表示主shard個數
rep:表示每個shard的複製個數
docs.count:表示index中document的個數 索引、讀取、刪除文檔
索引文檔 方法1:
輸入:
12
PUT /test1/user/1?pretty{"name": "silence1"}
輸出:
1234567
{ "_index" : "test1 "_type" : "user", "_id" : "1", "_version" : 1, "created" : true}
方法2:
輸入:
12
POST /test1/user/2?pretty{"name": "silence2"}
輸出:
1234567
{ "_index" : "test1", "_type" : "user", "_id" : "2", "_version" : 1, "created" : true}
方法3:
輸入:
12
POST /test1/user?pretty{"name": "silence3"}
輸出:
1234567
{ "_index" : "test1", "_type" : "user", "_id" : "AU_MdQoXRYiHSIs7UGBQ", "_version" : 1, "created" : true}
說明: 在索引文檔時若需要指定文檔ID值則需要使用PUT或者POST提交資料並顯示指定ID值,若需要由es自動產生ID,則需要使用POST提交資料
讀取文檔:
輸入: GET /test1/user/1?pretty
輸出:
12345678
{ "_index" : "test1", "_type" : "user", "_id" : "1", "_version" : 1, "found" : true, "_source":{"name": "silence1"}}
說明:
_index,_type:表示文檔儲存的Index和Type資訊
_id:表示文檔的編號
_version:表示文檔的版本號碼,主要用於並發處理時使用樂觀鎖防止髒資料
found:表示請求的文檔是否存在
_souce:格式為json,為文檔的內容
注意:在之前我們並未建立user的Type,在進行文檔索引時自動建立了user,在es中可以不顯示的建立Index和Type而使用預設參數或者根據提交資料自訂,但不建議這麼使用,在不清楚可能導致什麼情況時顯示建立Index和Type並設定參數
刪除文檔:
輸入: DELETE /test1/user/1?pretty
輸出:
1234567
{ "found" : true, "_index" : "test1", "_type" : "user", "_id" : "1", "_version" : 2}
再次讀取文檔輸出:
123456
{ "_index" : "test1", "_type" : "user", "_id" : "1", "found" : false}
刪除索引
輸入: DELETE /test1?pretty
輸出:
123
{ "acknowledged" : true}
修改文檔
初始化文檔輸入:
12
PUT /test1/user/1?pretty{"name" : "silence2", "age":28}
修改文檔輸入:
12
PUT /test1/user/1?pretty{"name" : "silence1"}
讀取文檔輸出:
12345678
{ "_index" : "test1", "_type" : "user", "_id" : "1", "_version" : 2, "found" : true, "_source":{"name" : "silence1"}}
更新文檔
更新資料輸入:
12
POST /test1/user/1/_update?pretty{"doc" : {"name" : "silence3", "age":28}}
讀取資料輸出:
12345678
{ "_index" : "test1", "_type" : "user", "_id" : "1", "_version" : 3, "found" : true, "_source":{"name":"silence3","age":28}}
更新文檔輸入:
12
POST /test1/user/1/_update?pretty{"script" : "ctx._source.age += 1"}
讀取文檔輸出:
12345678
{ "_index" : "test1", "_type" : "user", "_id" : "1", "_version" : 4, "found" : true, "_source":{"name":"silence3","age":29}}
說明:需要POST使用script則必須在elasticsearch/config/elasticsearch.yml配置script.groovy.sandbox.enabled: true
修改(PUT)和更新(POST+_update)的區別在於修改使用提交的文檔覆蓋es中的文檔,更新使用提交的參數值覆蓋es中文檔對應的參數值 根據查詢刪除文檔
輸入:
12
DELETE /test1/user/_query?pretty{"query" : {"match" : {"name" : "silence3"}}}
輸出:
1234567891011
{ "_indices" : { "test1" : { "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 } } }}
擷取文檔數量
輸入: GET /test1/user/_count?pretty
輸出:
12345678
{ "count" : 0, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }}
大量操作
輸入:
123456789
POST /test1/user/_bulk?pretty{"index" : {"_id" : 1}}{"name" : "silence1"}{"index" : {"_id" : 2}}{"name" : "silence2"}{"index" : {}}{"name" : "silence3"}{"index" : {}}{"name" : "silence4"}
輸入:
1234
POST /test1/user/_bulk?pretty{"update" : {"_id" : 1}}{"doc" : {"age" : 28}}{"delete" : {"_id" : 2}}
通過檔案匯入資料: curl -XPOST "localhost:9200/test1/account/_bulk?pretty" --data-binary @accounts.json Query查詢
查詢可以通過兩種方式進行,一種為使用查詢字串進行提交參數查詢,一種為使用RESTAPI提交requesbody提交參數查詢
擷取所有文檔輸入: GET /test1/user/_search?q=*&pretty
1234
POST /test1/user/_search?pretty{ "query" : {"match_all" : {}}}
輸出:
12345678910111213141516171819202122232425262728293031323334353637383940414243
{ "took": 2, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 1, "hits": [ { "_index": "test1", "_type": "user", "_id": "1", "_score": 1, "_source": { "name": "silence1", "age": 28 } }, { "_index": "test1", "_type": "user", "_id": "AU_M2zgwLNdQvgqQS3MP", "_score": 1, "_source": { "name": "silence3" } }, { "_index": "test1", "_type": "user", "_id": "AU_M2zgwLNdQvgqQS3MQ", "_score": 1, "_source": { "name": "silence4" } } ] }}
說明:
took: 執行查詢的時間(單位為毫秒)
timed_out: 執行不能逾時
_shards: 提示有多少shard參與查詢以及查詢成功和失敗shard數量
hits: 查詢結果
hits.total: 文檔總數
_score, max_score: 為文檔與查詢條件匹配度和最大匹配度 Query SDL
輸入:
123456789
POST /test1/account/_search?pretty{ "query" : {"match_all":{}}, "size": 2, "from" : 6, "sort" : { "age" : {"order" : "asc"} }}
說明:
query: 用於定義查詢條件過濾
match_all: 表示查詢所有文檔
size: 表示查詢返迴文檔數量,若未設定預設為10
from: 表示開始位置, es使用0作為開始索引,常與size組合進行分頁查詢,若未設定預設為0
sort: 用於設定排序屬性和規則 使用_source設定查詢結果返回的文件屬性
輸入:
1234567
POST /test1/account/_search?pretty{ "query": { "match_all": {} }, "_source":["firstname", "lastname", "age"]}
輸出:
12345678910111213141516171819202122232425262728293031323334353637
{ "took": 5, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1000, "max_score": 1, "hits": [ { "_index": "test1", "_type": "account", "_id": "4", "_score": 1, "_source": { "firstname": "Rodriquez", "age": 31, "lastname": "Flores" } }, { "_index": "test1", "_type": "account", "_id": "9", "_score": 1, "_source": { "firstname": "Opal", "age": 39, "lastname": "Meadows" } } ] }}
使用match設定查詢匹配值
輸入:
1234567
POST /test1/account/_search?pretty{ "query": { "match": {"address" : "986 Wyckoff Avenue"} }, "size" : 2}
輸出:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
{ "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 216, "max_score": 4.1231737, "hits": [ { "_index": "test1", "_type": "account", "_id": "4", "_score": 4.1231737, "_source": { "account_number": 4, "balance": 27658, "firstname": "Rodriquez", "lastname": "Flores", "age": 31, "gender": "F", "address": "986 Wyckoff Avenue", "employer": "Tourmania", "email": "rodriquezflores@tourmania.com", "city": "Eastvale", "state": "HI" } }, { "_index": "test1", "_type": "account", "_id": "34", "_score": 0.59278774, "_source": { "account_number": 34, "balance": 35379, "firstname": "Ellison", "lastname": "Kim", "age": 30, "gender": "F", "address": "986 Revere Place", "employer": "Signity", "email": "ellisonkim@signity.com", "city": "Sehili", "state": "IL" } } ] }}
說明:根據查詢結果可見在查詢結果中並非只查詢address包含”986 Wyckoff Avenue”的文檔,而是包含986,wychoff,Avenue三個詞中任意一個,這就是es分詞的強大之處
可見查詢結果中_score(與查詢條件匹配度)按從大到小的順序排列
此時你可能想要值查詢address包含”986 Wyckoff Avenue”的文檔,怎麼辦呢。使用match_phrase
輸入:
123456
POST /test1/account/_search?pretty{ "query": { "match_phrase": {"address" : "986 Wyckoff Avenue"} }}
可能你已經注意到, 以上query中只有一個條件,若存在多個條件,我們必須使用bool query將多個條件進行組合
輸入:
1234567891011
POST /test1/account/_search?pretty{ "query": { "bool" : { "must":[ {"match_phrase": {"address" : "986 Wyckoff Avenue"}}, {"match" : {"age" : 31}} ] } }}
說明: 查詢所有條件都滿足的結果
輸入:
1234567891011
POST /test1/account/_search{ "query": { "bool" : { "should":[ {"match_phrase": {"address" : "986 Wyckoff Avenue"}}, {"match_phrase": {"address" : "963 Neptune Avenue"}} ] } }}
說明: 查詢有一個條件滿足的結果
輸入:
1234567891011
POST /test1/account/_search{ "query": { "bool" : { "must_not":[ {"match": {"city" : "Eastvale"}}, {"match": {"city" : "Olney"}} ] } }}
說明: 查詢有條件都不滿足的結果
在Query SDL中可以將must, must_not和should組合使用
輸入:
12345678910111213
POST /test1/account/_search{ "query": { "bool" : { "must": [{ "match" : {"age":20} }], "must_not":[ {"match": {"city" : "Steinhatchee"}} ] } }}
Filters 查詢