本文根據ElasticSearch官方文件整理所得,簡單介紹ElasticSearch的概念以及一些簡單的檢索方法
首先下載ElasticSearch和Kibana到本地,注意這兩個東西的版本號要一致,然後啟動Kibana,開啟http://localhost:5601/app/kibana即可進入GUI的管理介面,進入Dev Tools即可操作ES。
1. 索引
先看ES中,索引的兩個概念:
儲存資料到 Elasticsearch 的行為叫做 索引(動詞) ,但在索引一個文件之前,需要確定將文件儲存在哪裡。
一個 Elasticsearch 叢集可以包含多個索引 (名詞),相應的每個索引可以包含多個型別。這些不同的型別儲存著多個文件* 每個文件又有多個屬性 。
可以看到上述語句不是很通順,主要是由於這裡的索引有兩個意思:
- 名詞,這裡的索引就像一個資料庫一樣。
- 動詞,索引(動詞)一個文件就是儲存一個文件到一個索引(名詞)中以便它可以被檢索和查詢到。就像SQL中的Insert一樣。
例子:
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
複製程式碼
路徑/megacorp/employee/1
包含了三部分的資訊:megacorp就是索引名稱(像資料庫),employee(像一張表),1(特定employee,就像標識每一行的主鍵)。接下來的JSON就是儲存的內容了。
2.檢索文件
檢索文件就像HTTP請求一樣,執行一個GET請求即可取回JSON文件:
GET /megacorp/employee/1
類似的GET還可以改為HEAD、DELETE等。
2.1輕量搜尋
搜尋所有僱員:
GET /megacorp/employee/_search
查詢JSON中的任意指定欄位:
GET /megacorp/employee/_search?q=last_name:Smith
使用查詢表示式搜尋,它支援構建更加複雜和健壯的查詢,使用請求體。:
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
複製程式碼
2.2複雜的查詢:
GET /megacorp/employee/_search
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}
複製程式碼
2.3 全文搜尋
全文搜尋可以完成傳統關係型資料庫很難做到的事情,如搜尋所有喜歡攀巖的僱員:
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
複製程式碼
這似乎與之前沒什麼不同啊?但是請看返回結果:
"hits": [
{
"_index": "megacorp",
"_type": "employee",
"_id": "1",
"_score": 0.53484553,
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
]
}
},
{
"_index": "megacorp",
"_type": "employee",
"_id": "2",
"_score": 0.26742277,
"_source": {
"first_name": "Jane",
"last_name": "Smith",
"age": 32,
"about": "I like to collect rock albums",
"interests": [
"music"
]
}
}
]
複製程式碼
Elasticsearch 預設按照相關性得分排序,即每個文件跟查詢的匹配程度。第一個最高得分的結果很明顯:John Smith 的 about
屬性清楚地寫著 “rock climbing” 。但是Jane也返回了,但是由於他的關鍵字裡並沒有完全匹配,所以他的相關性沒有John的高,排在後面。而傳統的關係型資料庫則是要麼匹配要麼完全不匹配。
2.3 短語匹配
那如果我想像關係型資料庫一樣只匹配完全符合的怎麼辦呢?就是用短語匹配的查詢:match_phrase
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
複製程式碼
則只會返回完全匹配的John的文件。
2.4 分析查詢
在使用聚合agg之前需要先對查詢的欄位加上fileddata=true,因為文件中寫道
Fielddata can consume a lot of heap space, especially when loading high cardinality
text
fields.
fileddata會消耗大量的堆空間,所以預設是關閉的,在這裡要手動開啟。
PUT megacorp/_mapping/employee/
{
"properties": {
"interests": {
"type": "text",
"fielddata": true
}
}
}
複製程式碼
有點像Group By:如找出Employee中最受歡迎的興趣愛好:
GET /megacorp/employee/_search
{
"aggs": {
"all_interests": {
"terms": { "field": "interests" }
}
}
},
複製程式碼
在輸出中可以看到,每個interest按照人數排序:
{
...
"hits": { ... },
"aggregations": {
"all_interests": {
"buckets": [
{
"key": "music",
"doc_count": 2
},
{
"key": "forestry",
"doc_count": 1
},
{
"key": "sports",
"doc_count": 1
}
]
}
}
}
複製程式碼
這個aggs欄位還可以作為query欄位的子查詢。如:
GET /megacorp/employee/_search
{
"query": {
"match": {
"last_name": "smith"
}
},
"aggs": {
"all_interests": {
"terms": {
"field": "interests"
}
}
}
}
複製程式碼
還支援分級彙總,如查詢每個興趣的員工平均年齡:
GET /megacorp/employee/_search
{
"aggs" : {
"all_interests" : {
"terms" : { "field" : "interests" },
"aggs" : {
"avg_age" : {
"avg" : { "field" : "age" }
}
}
}
}
}
複製程式碼
3. 分散式特性
Elasticsearch 儘可能地遮蔽了分散式系統的複雜性。這裡列舉了一些在後臺自動執行的操作:
- 分配文件到不同的容器 或分片中,文件可以儲存在一個或多個節點中
- 按叢集節點來均衡分配這些分片,從而對索引和搜尋過程進行負載均衡
- 複製每個分片以支援資料冗餘,從而防止硬體故障導致的資料丟失
- 將叢集中任一節點的請求路由到存有相關資料的節點
- 叢集擴容時無縫整合新節點,重新分配分片以便從離群節點恢復