聲明:
本文轉(zhuǎn)自我的個人博客扭仁,有興趣的可以查看原文垮衷。
轉(zhuǎn)發(fā)請注明來源。
這是一篇科普文搀突。
1. 背景
Elasticsearch 在公司的使用越來越廣涩赢,很多同事之前并沒有接觸過 Elasticsearch,所以花墩,最近在公司準備了一次關(guān)于 Elasticsearch 的分享,整理成此文祠肥。此文面向 Elasticsearch 新手,老司機們可以撤了剂桥。
2. 倒排索引
先簡單介紹下搜索引擎的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)倒排索引。
我們在平時斟薇,會經(jīng)常使用各種各樣的索引,如我們根據(jù)鏈接,可以找到鏈接里的具體文本犯眠,這就是索引。反過來铺罢,如果,如果我們能根據(jù)具體文本泉瞻,找到文本存在的具體鏈接,這就是倒排索引舅锄,可簡單理解為從文本到鏈接的映射畴蹭。我們平時在使用Google撮胧、百度時锻离,就是根據(jù)具體文本去找鏈接汽纠,這就是以倒排索引為基礎(chǔ)的莉炉。
可參看維基百科 絮宁。
3. Elasticsearch 簡介與基本概念
Elasticsearch is a real-time distributed search and analytics engine. It allows you to explore your data at a speed and at a scale never before possible. It is used for full-text search, structured search, analytics, and all three in combination.
在 《Elasticsearch : The Definitive Guide》里,這樣介紹Elasticsearch唠椭,總的來說贪嫂,Elasticsearch 是一個分布式的搜索和分析引擎饶深,可以用于全文檢索俱两、結(jié)構(gòu)化檢索和分析,并能將這三者結(jié)合起來尿孔。Elasticsearch 基于 Lucene 開發(fā)俊柔,現(xiàn)在是使用最廣的開源搜索引擎之一,Wikipedia活合、Stack Overflow雏婶、GitHub 等都基于 Elasticsearch 來構(gòu)建他們的搜索引擎。
先介紹下 Elasticsearch 里的基本概念白指,下圖是 Elasticsearch 插件 head 的一個截圖留晚。
- node:即一個 Elasticsearch 的運行實例,使用多播或單播方式發(fā)現(xiàn) cluster 并加入告嘲。
- cluster:包含一個或多個擁有相同集群名稱的 node错维,其中包含一個master node。
- index:類比關(guān)系型數(shù)據(jù)庫里的DB橄唬,是一個邏輯命名空間赋焕。
- alias:可以給 index 添加零個或多個alias,通過 alias 使用index 和根據(jù)index name 訪問index一樣轧坎,但是宏邮,alias給我們提供了一種切換index的能力,比如重建了index,取名customer_online_v2蜜氨,這時械筛,有了alias,我要訪問新 index飒炎,只需要把 alias 添加到新 index 即可埋哟,并把alias從舊的 index 刪除。不用修改代碼郎汪。
- type:類比關(guān)系數(shù)據(jù)庫里的Table赤赊。其中,一個index可以定義多個type煞赢,但一般使用習(xí)慣僅配一個type抛计。
- mapping:類比關(guān)系型數(shù)據(jù)庫中的 schema 概念,mapping 定義了 index 中的 type照筑。mapping 可以顯示的定義吹截,也可以在 document 被索引時自動生成,如果有新的 field凝危,Elasticsearch 會自動推測出 field 的type并加到mapping中波俄。
- document:類比關(guān)系數(shù)據(jù)庫里的一行記錄(record),document 是 Elasticsearch 里的一個 JSON 對象蛾默,包括零個或多個field懦铺。
- field:類比關(guān)系數(shù)據(jù)庫里的field,每個field 都有自己的字段類型支鸡。
- shard:是一個Lucene 實例冬念。Elasticsearch 基于 Lucene,shard 是一個 Lucene 實例苍匆,被 Elasticsearch 自動管理刘急。之前提到棚菊,index 是一個邏輯命名空間浸踩,shard 是具體的物理概念,建索引统求、查詢等都是具體的shard在工作检碗。shard 包括primary shard 和 replica shard,寫數(shù)據(jù)時码邻,先寫到primary shard折剃,然后,同步到replica shard像屋,查詢時怕犁,primary 和 replica 充當相同的作用。replica shard 可以有多份,也可以沒有奏甫,replica shard的存在有兩個作用戈轿,一是容災(zāi),如果primary shard 掛了阵子,數(shù)據(jù)也不會丟失思杯,集群仍然能正常工作;二是提高性能挠进,因為replica 和 primary shard 都能處理查詢色乾。另外,如上圖右側(cè)紅框所示领突,shard數(shù)和replica數(shù)都可以設(shè)置暖璧,但是留储,shard 數(shù)只能在建立index 時設(shè)置役衡,后期不能更改,但是挚歧,replica 數(shù)可以隨時更改于宙。但是浮驳,由于 Elasticsearch 很友好的封裝了這部分,在使用Elasticsearch 的過程中捞魁,我們一般僅需要關(guān)注 index 即可至会,不需關(guān)注shard。
綜上所述谱俭,shard奉件、node、cluster 在物理上構(gòu)成了 Elasticsearch 集群昆著,field县貌、type、index 在邏輯上構(gòu)成一個index的基本概念凑懂,在使用 Elasticsearch 過程中煤痕,我們一般關(guān)注到邏輯概念就好,就像我們在使用MySQL 時接谨,我們一般就關(guān)注DB Name摆碉、Table和schema即可,而不會關(guān)注DBA維護了幾個MySQL實例脓豪、master 和 slave 等怎么部署的一樣巷帝。
下表用Elasticsearch 和 關(guān)系數(shù)據(jù)庫做了類比:
- index => databases
- type => table
- field => field
- document => record
- mapping => schema
最后,來從 Elasticsearch 中取出一條數(shù)據(jù)(document)看看:
由index扫夜、type和id三者唯一確定一個document楞泼,_source 字段中是具體的document 值驰徊,是一個JSON 對象,有5個field組成堕阔。
4. Elasticsearch 基本使用
下面介紹下 Elasticsearch 的基本使用辣垒,這里僅介紹 Elasticsearch 能做什么,而不詳細介紹語法印蔬。
4.1 基礎(chǔ)操作
- index:寫 document 到 Elasticsearch 中勋桶,如果不存在,就創(chuàng)建侥猬,如果存在例驹,就用新的取代舊的。
- create:寫 document 到 Elasticsearch 中退唠,與 index 不同的是鹃锈,如果存在,就拋出異常
DocumentAlreadyExistException
瞧预。 - get:根據(jù)ID取出document屎债。
- update:如果是更新整個 document,可用index 操作垢油。如果是部分更新盆驹,用update操作。在Elasticsearch中滩愁,更新document時躯喇,是把舊數(shù)據(jù)取出來,然后改寫要更新的部分硝枉,刪除舊document廉丽,創(chuàng)建新document,而不是在原document上做修改妻味。
- delete:刪除document正压。Elasticsearch 會標記刪除document,然后责球,在Lucene 底層進行merge時焦履,會刪除標記刪除的document。
4.2 Filter 與 Query
Elasticsearch 使用 domain-specific language(DSL)進行查詢棕诵,DSL 使用 JSON 進行表示裁良。
DSL 由一些子查詢組成,這些子查詢可應(yīng)用于兩類查詢校套,分別是filter 和 query。
filter 正如其字面意思“過濾”所說的牧抵,是起過濾的作用笛匙,任何一個document 對 filter 來說侨把,就是match 與否的問題,是個二值問題妹孙,0和1秋柄,沒有scoring的過程。
使用query的時候蠢正,是表示match 程度問題骇笔,有scroing 過程。
另外嚣崭,F(xiàn)ilter 和 Query 還有性能上的差異笨触,Elasticsearch 底層對Filter做了很多優(yōu)化,會對過濾結(jié)果進行緩存雹舀;同時芦劣,F(xiàn)ilter 沒有相關(guān)性計算過程,所以说榆,F(xiàn)ilter 比 Query 快虚吟。
所以,官網(wǎng)推薦签财,作為一條比較通用的規(guī)則串慰,僅在全文檢索時使用Query,其它時候都用Filter唱蒸。但是模庐,根據(jù)我們的使用情況來看,在過濾條件不是很強的情況下油宜,緩存可能會占用較多內(nèi)存掂碱,如果這些數(shù)據(jù)不是頻繁使用,用空間換時間不一定劃算慎冤。
4.3 一些重要的查詢
在Elasticsearch 中疼燥,有幾類最重要的查詢子句,掌握了就可以覆蓋日常90%以上的需求蚁堤。
4.3.1 match_all
{"match_all":{}}
表示取出所有documents醉者,在與filter結(jié)合使用時,會經(jīng)常使用match_all披诗。
4.3.2 match
一般在全文檢索時使用撬即,首先利用analyzer 對具體查詢字符串進行分析,然后進行查詢呈队;如果是在數(shù)值型字段剥槐、日期類型字段、布爾字段或not_analyzed 的字符串上進行查詢時宪摧,不對查詢字符串進行分析粒竖,表示精確匹配颅崩,兩個簡單的例子如:
{ "match": { "tweet": "About Search" }}
{ "match": { "age": 26 }}
4.3.3 term
term 用于精確查找,可用于數(shù)值蕊苗、date沿后、boolean值或not_analyzed string,當使用term時朽砰,不會對查詢字符串進行分析尖滚,進行的是精確查找。
{ "term": { "date": "2014-09-01" }}
4.3.4 terms
terms 和 term 類似瞧柔,但是漆弄,terms 里可以指定多個值,只要doc滿足terms 里的任意值非剃,就是滿足查詢條件的置逻。與term 相同,terms 也是用于精確查找备绽。
{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
注意券坞,terms 表示的是contains 關(guān)系,而不是 equals關(guān)系肺素。
4.3.5 range
類比數(shù)據(jù)庫查找的范圍查找恨锚,舉個簡單的例子:
{
"range": {
"age": {
"gte": 20,
"lt": 30
}
}
}
操作符可以是:
- gt:大于
- gte:大于等于
- lt:小于
- lte:小于等于
4.3.6 exists 和 missing
exists 用于查找字段含有一個或多個值的document,而missing用于查找某字段不存在值的document倍靡,可類比關(guān)系數(shù)據(jù)庫里的 is not null (exists) 和 is null (missing).
{
"exists": {
"field": "title"
}
}
4.3.7 bool
前面講的都是些最原子的查詢子句猴伶,那么,怎么實現(xiàn)復(fù)合查詢呢塌西?Elasticsearch 使用bool 子句來將各種子查詢關(guān)聯(lián)起來他挎,組成布爾表達式,bool 子句可以隨意組合捡需、嵌套办桨。
bool子句主要包括:
- must:表示必須匹配。
- must_not:表示一定不能匹配站辉。
- should:表示可以匹配呢撞,類似于布爾運算里的"或"。如果bool 子句里饰剥,沒有must子句殊霞,那么,should子句里至少匹配一個汰蓉,如果有must子句绷蹲,那么,should子句至少匹配零個古沥∪秤遥可以使用
minimum_should_match
來對最小匹配數(shù)進行設(shè)置娇跟。
{
"bool" : {
"must" : {
"term" : { "user" : "kimchy" }
},
"must_not" : {
"range" : {
"age" : { "from" : 10, "to" : 20 }
}
},
"should" : [
{
"term" : { "tag" : "wow" }
},
{
"term" : { "tag" : "elasticsearch" }
}
],
"minimum_should_match" : 1,
"boost" : 1.0
}
}
4.4 聚合功能
前面說的都是 Elasticsearch 當做搜索引擎使用岩齿,Elasticsearch 還可以作為分析引擎使用太颤。
和 MySQL 等關(guān)系數(shù)據(jù)庫類似,Elasticsearch 有聚合操作盹沈,而且龄章,可作用于大量數(shù)據(jù),提供實時的分析結(jié)果乞封,速度快做裙;同時,聚合操作可以與搜索結(jié)合使用肃晚,例如將聚合作用于搜索結(jié)果等锚贱。總之关串,Elasticsearch的聚合功能十分強大拧廊,有很多公司利用 Elasticsearch 來做分析,其中晋修,廣泛使用的 ELK(Elasticsearch + Logstash + Kibana)吧碾,Kibana的數(shù)據(jù)顯示和分析功能就是基于 Elasticsearch 的聚合功能做的。
具體可參看 Elasticsearch: The Definitive Guide
4.5 Geolocation
Elasticsearch 還提供了基于地理位置的搜索墓卦,而且能將地理位置與全文檢索倦春、結(jié)構(gòu)化搜索、分析等結(jié)合起來使用落剪,比如查找距離某點一定范圍內(nèi)的符合搜索條件的地點睁本、計算兩點的距離、判斷兩個形狀是否相交或包含等忠怖。
具體參考 Elasticsearch: The Definitive Guide
5. Elasticsearch 使用時注意的幾個問題
深度分頁問題:Elasticsearch 作為一個分布式搜索與分析引擎呢堰,深度分頁問題會帶來嚴重的問題,給CPU脑又、內(nèi)存暮胧、IO、網(wǎng)絡(luò)帶來巨大壓力问麸,所以往衷,在Elasticsearch 不建議使用深度分頁,如果要遍歷數(shù)據(jù)严卖,可以采用 SCROLL的方式席舍,可參考我另一篇博客。
排序問題:根據(jù)某field排序時哮笆,Elasticsearch 會將這個 field 的所有值給加載到內(nèi)存来颤,然后汰扭,這部分數(shù)據(jù)會常駐內(nèi)存,如果數(shù)據(jù)量大或排序字段多福铅,就會給系統(tǒng)帶來巨大壓力萝毛,所以,在使用 field 進行排序時滑黔,要慎重笆包。不過,在Elasticsearch 2.X版本略荡,開始使用 doc value 來優(yōu)化這部分庵佣。
terms 問題: terms 里可以傳多個值,但是汛兜,量不能太多巴粪,搜索引擎的基本數(shù)據(jù)結(jié)構(gòu)是倒排索引,terms 里傳多個值粥谬,原理上來說是查很多的倒排索引肛根,量大了也會給系統(tǒng)帶來很大壓力。
6 總結(jié)
本文是一篇 Elasticsearch 的入門文章帝嗡,涵蓋的是一些基本概念晶通,篇幅有限,并不深入哟玷,如DSL的具體語法狮辽、聚合功能等都點到為止,希望大家知道的是Elasticsearch能干什么巢寡,具體要做的時候喉脖,再去詳查就好了。