Elasticsearch簡介與實戰
什麼是Elasticsearch?
Elasticsearch是一個開源的分布式、RESTful 風格的搜尋和資料分析引擎,它的底層是開源庫Apache Lucene。
Lucene 可以說是當下最先進、高性能、全功能的搜尋引擎庫——無論是開源還是私有,但它也僅僅隻是一個庫。為了充分發揮其功能,你需要使用 Java 并将 Lucene 直接內建到應用程式中。 更糟糕的是,您可能需要獲得資訊檢索學位才能了解其工作原理,因為Lucene 非常複雜。
為了解決Lucene使用時的繁複性,于是Elasticsearch便應運而生。它使用 Java 編寫,内部采用 Lucene 做索引與搜尋,但是它的目标是使全文檢索變得更簡單,簡單來說,就是對Lucene 做了一層封裝,它提供了一套簡單一緻的 RESTful API 來幫助我們實作存儲和檢索。
當然,Elasticsearch 不僅僅是 Lucene,并且也不僅僅隻是一個全文搜尋引擎。 它可以被下面這樣準确地形容:
- 一個分布式的實時文檔存儲,每個字段可以被索引與搜尋;
- 一個分布式實時分析搜尋引擎;
- 能勝任上百個服務節點的擴充,并支援 PB 級别的結構化或者非結構化資料。
由于Elasticsearch的功能強大和使用簡單,維基百科、衛報、Stack Overflow、GitHub等都紛紛采用它來做搜尋。現在,Elasticsearch已成為全文搜尋領域的主流軟體之一。
下面将介紹Elasticsearch的安裝與簡單使用。
安裝并運作Elasticsearch
安裝 Elasticsearch 之前,你需要先安裝一個較新版本的 Java,最好的選擇是,你可以從 www.java.com 獲得官方提供的最新版本的Java。
你可以從 elastic 的官網 elastic.co/downloads/elasticsearch 擷取最新版本的Elasticsearch。解壓文檔後,按照下面的操作,即可在前台(foregroud)啟動 Elasticsearch:
cd elasticsearch-<version>
./bin/elasticsearch
此時,Elasticsearch運作在本地的9200端口,在浏覽器中輸入網址“http://localhost:9200/”,如果看到以下資訊就說明你的電腦已成功安裝Elasticsearch:
{
"name" : "YTK8L4q",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "hB2CZPlvSJavhJxx85fUqQ",
"version" : {
"number" : "6.5.4",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
在這裡,我們安裝的Elasticsearch版本号為6.5.4。
Kibana 是一個開源的分析和可視化平台,旨在與 Elasticsearch 合作。Kibana 提供搜尋、檢視和與存儲在 Elasticsearch 索引中的資料進行互動的功能。開發者或運維人員可以輕松地執行進階資料分析,并在各種圖表、表格和地圖中可視化資料。
你可以從 elastic 的官網 https://www.elastic.co/downloads/kibana 擷取最新版本的Kibana。解壓文檔後,按照下面的操作,即可在前台(foregroud)啟動Kibana:
cd kibana-<version>
./bin/kabana
此時,Kibana運作在本地的5601端口,在浏覽器中輸入網址“http://localhost:5601”,即可看到以下界面:
Kibana啟動界面
下面,讓我們來了解Elasticsearch的一些基本概念,這有助于我們更好地了解和使用Elasticsearch。
Elasticsearch基本概念
全文搜尋(Full-text Search)
全文檢索是指計算機索引程式通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當使用者查詢時,檢索程式就根據事先建立的索引進行查找,并将查找的結果回報給使用者的檢索方式。
在全文搜尋的世界中,存在着幾個龐大的帝國,也就是主流工具,主要有:
- Apache Lucene
- Elasticsearch
- Solr
- Ferret
反向索引(Inverted Index)
該索引表中的每一項都包括一個屬性值和具有該屬性值的各記錄的位址。由于不是由記錄來确定屬性值,而是由屬性值來确定記錄的位置,因而稱為反向索引(inverted index)。Elasticsearch能夠實作快速、高效的搜尋功能,正是基于反向索引原理。
節點 & 叢集(Node & Cluster)
Elasticsearch 本質上是一個分布式資料庫,允許多台伺服器協同工作,每台伺服器可以運作多個Elasticsearch執行個體。單個Elasticsearch執行個體稱為一個節點(Node),一組節點構成一個叢集(Cluster)。
索引(Index)
Elasticsearch 資料管理的頂層機關就叫做 Index(索引),相當于關系型資料庫裡的資料庫的概念。另外,每個Index的名字必須是小寫。
文檔(Document)
Index裡面單條的記錄稱為 Document(文檔)。許多條 Document 構成了一個 Index。Document 使用 JSON 格式表示。同一個 Index 裡面的 Document,不要求有相同的結構(scheme),但是最好保持相同,這樣有利于提高搜尋效率。
類型(Type)
Document 可以分組,比如employee這個 Index 裡面,可以按部門分組,也可以按職級分組。這種分組就叫做 Type,它是虛拟的邏輯分組,用來過濾 Document,類似關系型資料庫中的資料表。
不同的 Type 應該有相似的結構(Schema),性質完全不同的資料(比如 products 和 logs)應該存成兩個 Index,而不是一個 Index 裡面的兩個 Type(雖然可以做到)。
文檔中繼資料(Document metadata)
文檔中繼資料為_index, _type, _id, 這三者可以唯一表示一個文檔,_index表示文檔在哪存放,_type表示文檔的對象類别,_id為文檔的唯一辨別。
字段(Fields)
每個Document都類似一個JSON結構,它包含了許多字段,每個字段都有其對應的值,多個字段組成了一個 Document,可以類比關系型資料庫資料表中的字段。
在 Elasticsearch 中,文檔(Document)歸屬于一種類型(Type),而這些類型存在于索引(Index)中,下圖展示了Elasticsearch與傳統關系型資料庫的類比:
Elasticsearch入門
Elasticsearch提供了多種互動使用方式,包括Java API和RESTful API ,本文主要介紹RESTful API 。所有其他語言可以使用RESTful API 通過端口 9200 和 Elasticsearch 進行通信,你可以用你最喜愛的 web 用戶端通路 Elasticsearch 。甚至,你還可以使用
curl
指令來和 Elasticsearch 互動。
一個Elasticsearch請求和任何 HTTP 請求一樣,都由若幹相同的部件組成:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
傳回的資料格式為JSON,因為Elasticsearch中的文檔以JSON格式儲存。其中,被
< >
标記的部件:
部件 | 說明 |
---|---|
VERB | 适當的 HTTP 方法 或 謂詞 : 、 、 、 或者 。 |
PROTOCOL | 或者 (如果你在 Elasticsearch 前面有一個 代理) |
HOST | Elasticsearch 叢集中任意節點的主機名,或者用 代表本地機器上的節點。 |
PORT | 運作 Elasticsearch HTTP 服務的端口号,預設是 。 |
PATH | API 的終端路徑(例如 将傳回叢集中文檔數量)。Path 可能包含多個元件,例如: 和 。 |
QUERY_STRING | 任意可選的查詢字元串參數 (例如 将格式化地輸出 JSON 傳回值,使其更容易閱讀) |
BODY | 一個 JSON 格式的請求體 (如果請求需要的話) |
對于HTTP方法,它們的具體作用為:
HTTP方法 | 說明 |
---|---|
GET | 擷取請求對象的目前狀态 |
POST | 改變對象的目前狀态 |
PUT | 建立一個對象 |
DELETE | 銷毀對象 |
HEAD | 請求擷取對象的基礎資訊 |
我們以下面的資料為例,來展示Elasticsearch的用法。
以下全部的操作都在Kibana中完成,建立的index為conference, type為event .
插入資料
首先建立index為conference, 建立type為event, 插入id為1的第一條資料,隻需運作下面指令就行:
PUT /conference/event/1
{
"host": "Dave",
"title": "Elasticsearch at Rangespan and Exonar",
"description": "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
"attendees": ["Dave", "Andrew", "David", "Clint"],
"date": "2013-06-24T18:30",
"reviews": 3
}
在上面的指令中,路徑/conference/event/1表示文檔的index為conference, type為event, id為1. 類似于上面的操作,依次插入剩餘的4條資料,完成插入後,檢視資料如下:
插入資料
删除資料
比如我們想要删除conference中event裡面id為5的資料,隻需運作下面指令即可:
DELETE /conference/event/5
傳回結果如下:
{
"_index" : "conference",
"_type" : "event",
"_id" : "5",
"_version" : 2,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
表示該文檔已成功删除。如果想删除整個event類型,可輸入指令:
DELETE /conference/event
如果想删除整個conference索引,可輸入指令:
DELETE /conference
修改資料
修改資料的指令為POST, 比如我們想要将conference中event裡面id為4的文檔的作者改為Bob,那麼需要運作指令如下:
POST /conference/event/4/_update
{
"doc": {"host": "Bob"}
}
傳回的資訊如下:(表示修改資料成功)
{
"_index" : "conference",
"_type" : "event",
"_id" : "4",
"_version" : 7,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 7,
"_primary_term" : 1
}
檢視修改後的資料如下:
修改資料
查詢資料
查詢資料的指令為GET,查詢指令也是Elasticsearch最為重要的功能之一。比如我們想查詢conference中event裡面id為1的資料,運作指令如下:
GET /conference/event/1
傳回的結果如下:
{
"_index" : "conference",
"_type" : "event",
"_id" : "1",
"_version" : 2,
"found" : true,
"_source" : {
"host" : "Dave",
"title" : "Elasticsearch at Rangespan and Exonar",
"description" : "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
"attendees" : [
"Dave",
"Andrew",
"David",
"Clint"
],
"date" : "2013-06-24T18:30",
"reviews" : 3
}
}
在_source 屬性中,内容是原始的 JSON 文檔,還包含有其它屬性,比如_index, _type, _id, _found等。
如果想要搜尋conference中event裡面所有的文檔,運作指令如下:
GET /conference/event/_search
傳回結果包括了所有四個文檔,放在數組 hits 中。
當然,Elasticsearch 提供更加豐富靈活的查詢語言叫做 查詢表達式 , 它支援建構更加複雜和健壯的查詢。利用查詢表達式,我們可以檢索出conference中event裡面所有host為Bob的文檔,指令如下:
GET /conference/event/_search
{
"query" : {
"match" : {
"host" : "Bob"
}
}
}
傳回的結果隻包括了一個文檔,放在數組 hits 中。
接着,讓我們嘗試稍微進階點兒的全文搜尋——一項傳統資料庫确實很難搞定的任務。搜尋下所有description中含有"use Elasticsearch"的event:
GET /conference/event/_search
{
"query" : {
"match" : {
"description" : "use Elasticsearch"
}
}
}
傳回的結果(部分)如下:
{
...
"hits" : {
"total" : 2,
"max_score" : 0.65109104,
"hits" : [
{
...
"_score" : 0.65109104,
"_source" : {
"host" : "Dave Nolan",
"title" : "real-time Elasticsearch",
"description" : "We will discuss using Elasticsearch to index data in real time",
...
}
},
{
...
"_score" : 0.5753642,
"_source" : {
"host" : "Dave",
"title" : "Elasticsearch at Rangespan and Exonar",
"description" : "Representatives from Rangespan and Exonar will come and discuss how they use Elasticsearch",
...
}
}
]
}
}
傳回的結果包含了兩個文檔,放在數組 hits 中。讓我們對這個結果做一些分析,第一個文檔的description裡面含有“using Elasticsearch”,這個能比對“use Elasticsearch”是因為Elasticsearch含有内置的詞幹提取算法,之後兩個文檔按_score進行排序,_score字段表示文檔的相似度(預設的相似度算法為BM25)。
如果想搜尋下所有description中嚴格含有"use Elasticsearch"這個短語的event,可以使用下面的指令:
GET /conference/event/_search
{
"query" : {
"match_phrase": {
"description" : "use Elasticsearch"
}
}
}
這時候傳回的結果隻有一個文檔,就是上面輸出的第二個文檔。
當然,Elasticsearch還支援更多的搜尋功能,比如過濾器,高亮搜尋,結構化搜尋等,希望接下來能有更多的時間和經曆來介紹~