ElasticSearch學習一-小試牛刀

Hugo_Gao發表於2019-03-03

本文根據ElasticSearch官方文件整理所得,簡單介紹ElasticSearch的概念以及一些簡單的檢索方法

首先下載ElasticSearch和Kibana到本地,注意這兩個東西的版本號要一致,然後啟動Kibana,開啟http://localhost:5601/app/kibana即可進入GUI的管理介面,進入Dev Tools即可操作ES。

1. 索引

先看ES中,索引的兩個概念:

儲存資料到 Elasticsearch 的行為叫做 索引(動詞) ,但在索引一個文件之前,需要確定將文件儲存在哪裡。

一個 Elasticsearch 叢集可以包含多個索引 (名詞),相應的每個索引可以包含多個型別。這些不同的型別儲存著多個文件* 每個文件又有多個屬性 。

可以看到上述語句不是很通順,主要是由於這裡的索引有兩個意思:

  1. 名詞,這裡的索引就像一個資料庫一樣。
  2. 動詞,索引(動詞)一個文件就是儲存一個文件到一個索引(名詞)中以便它可以被檢索和查詢到。就像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 儘可能地遮蔽了分散式系統的複雜性。這裡列舉了一些在後臺自動執行的操作:

  • 分配文件到不同的容器 或分片中,文件可以儲存在一個或多個節點中
  • 按叢集節點來均衡分配這些分片,從而對索引和搜尋過程進行負載均衡
  • 複製每個分片以支援資料冗餘,從而防止硬體故障導致的資料丟失
  • 將叢集中任一節點的請求路由到存有相關資料的節點
  • 叢集擴容時無縫整合新節點,重新分配分片以便從離群節點恢復

相關文章