索引模板,簡(jiǎn)而言之仓坞,是一種復(fù)用機(jī)制背零,就像一些項(xiàng)目的開(kāi)發(fā)框架如 Laravel 一樣,省去了大量的重復(fù)无埃,體力勞動(dòng)徙瓶。當(dāng)新建一個(gè) Elasticsearch 索引時(shí)毛雇,自動(dòng)匹配模板,完成索引的基礎(chǔ)部分搭建侦镇。
典型的如下所示:
{
"order": 0,
"template": "sample_info*",
"settings": {
"index": {
"number_of_shards": "64",
"number_of_replicas": "1"
}
},
"mappings": {
"info": {
"dynamic_templates": [
{
"string_fields": {
"mapping": {
"analyzer": "only_words_analyzer",
"index": "analyzed",
"type": "string",
"fields": {
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
},
"match_mapping_type": "string",
"match": "*"
}
}
]灵疮,
"properties": {
"user_province": {
"analyzer": "lowercase_analyzer",
"index": "analyzed",
"type": "string",
"fields": {
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
}
}
}
},
"aliases": {}
}
上述模板定義,看似復(fù)雜虽缕,拆分來(lái)看始藕,主要為如下幾個(gè)部分:
{
"order": 0, // 模板優(yōu)先級(jí)
"template": "sample_info*", // 模板匹配的名稱(chēng)方式
"settings": {...}, // 索引設(shè)置
"mappings": {...}, // 索引中各字段的映射定義
"aliases": {...} // 索引的別名
}
1、模板優(yōu)先級(jí)
有時(shí)候氮趋,一個(gè)模板可能絕大部分符合新建索引的需求伍派,但是局部需要微調(diào),此時(shí)剩胁,如果復(fù)制舊的模板诉植,修改該模板后,成為一個(gè)新的索引模板即可達(dá)到我們的需求昵观,但是這操作略顯重復(fù)晾腔。此時(shí),可以采用模板疊加與覆蓋來(lái)操作啊犬。模板的優(yōu)先級(jí)是通過(guò)模板中的 order 字段定義的灼擂,數(shù)字越大,優(yōu)先級(jí)越高觉至。
如下為定義所有以 te 開(kāi)頭的索引的模板:
{
"order": 0
"template" : "te*",
"settings" : {
"number_of_shards" : 1
},
"mappings" : {
"type1" : {
"_source" : { "enabled" : false }
}
}
}
索引模板是有序合并的剔应。如何想單獨(dú)修改某一小類(lèi)索引的一兩處單獨(dú)設(shè)置,可以在累加一層模板语御。
{
"order" : 1,
"template" : "tete*",
"settings" : {
"number_of_shards" : 2
},
"mappings" : {
"type1" : {
"_all" : { "enabled" : false }
}
}
}
上述第一個(gè)模板的 order 為0峻贮,第二個(gè)模板的 order 為1,優(yōu)先級(jí)高于第一個(gè)模板应闯,其會(huì)覆蓋第一個(gè)模板中的相同項(xiàng)纤控。所以對(duì)于所有以 tete 開(kāi)頭的索引模板效果如下:
{
"settings" : {
"number_of_shards" : 2
},
"mappings" : {
"type1" : {
"_source" : { "enabled" : false },
"_all" : { "enabled" : false }
}
}
}
兩個(gè)模板疊加了,項(xiàng)目的字段碉纺,優(yōu)先級(jí)高的覆蓋了優(yōu)先級(jí)低的船万,如分片數(shù)。
2骨田、索引模板的匹配
索引模板中的 "template" 字段定義的是該索引模板所應(yīng)用的索引情況唬涧。如 "template": "tete*" 所表示的含義是,當(dāng)新建索引時(shí)盛撑,所有以 tete 開(kāi)頭的索引都會(huì)自動(dòng)匹配到該索引模板。利用該模板進(jìn)行相應(yīng)的設(shè)置和字段添加等捧搞。
3抵卫、setting 部分
索引模板中的 setting 部分一般定義的是索引的主分片狮荔、拷貝分片、刷新時(shí)間介粘、自定義分析器等殖氏。常見(jiàn)的 setting 部分結(jié)構(gòu)如下:
"settings": {
"index": {
"analysis": {...}, // 自定義的分析器
"number_of_shards": "32", // 主分片的個(gè)數(shù)
"number_of_replicas": "1", // 主分片的拷貝分片個(gè)數(shù)
"refresh_interval": "5s" // 刷新時(shí)間
}
}
建立的索引,不會(huì)立馬查到姻采,這是為什么 Elasticsearch 為 near-real-time(接近實(shí)時(shí))的原因雅采,需要配置刷新時(shí)間,默認(rèn)的是 1s慨亲。setting 的設(shè)置中婚瓜,重點(diǎn)是自定義分析器的設(shè)置。
分析器是三個(gè)順序執(zhí)行的組件的結(jié)合刑棵。他們分別是字符過(guò)濾器巴刻、分詞器、標(biāo)記過(guò)濾器蛉签。
- 字符過(guò)濾器是讓字符串在被分詞前變得更加整潔胡陪。一個(gè)分析器可能包含零到多個(gè)字符過(guò)濾器(character_filter)。
- 分詞器將字符串分割成單獨(dú)的詞(terms)或標(biāo)記(tokens)碍舍。一個(gè)分析器必須包含一個(gè)分詞器柠座。
- 分詞器分詞的結(jié)果的標(biāo)記流會(huì)根據(jù)各自的情況,傳遞給特定的標(biāo)記過(guò)濾器片橡。標(biāo)記過(guò)濾器可能修改妈经、添加或刪除標(biāo)記。
創(chuàng)建的創(chuàng)建自定義分析器結(jié)構(gòu)如下:
"settings": {
"index": {
"analysis": {
"char_filter": { ... }, // 用戶(hù)自定義字符過(guò)濾器
"tokenizer": { ... }, // 用戶(hù)自定義分詞器
"filter": { ... }, // 用戶(hù)自定義標(biāo)記過(guò)濾器
"analyzer": { ... } // 用戶(hù)自定義分析器
},
...
}
}
1)字符過(guò)濾器
目前字符過(guò)濾器共分為三種:映射字符過(guò)濾器(mapping char filter)锻全、HTML過(guò)濾器(HTML Strip char filter)狂塘、格式替換過(guò)濾器(Pattern Replace char filter)。html_strip 字符過(guò)濾器去除所有的 HTML 標(biāo)簽鳄厌。
如下定義一個(gè) mapping 字符過(guò)去器荞胡。將 & 替換成 and。
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": [ "&=> and "]
}
}
mapping 字符過(guò)濾器的格式如上了嚎,其中 type 字段定義該字符過(guò)濾器的類(lèi)型是 mapping 泪漂。其中 mappings 對(duì)應(yīng)的數(shù)組為索要替換的字段。
如下在定義一個(gè)格式替換過(guò)濾器(Pattern Replace Char Filter)歪泳,將點(diǎn) "." 替換成空格萝勤。
"char_filter": {
"replace_dot": {
"pattern": "\\.",
"type": "pattern_replace",
"replacement": " "
}
}
格式替換過(guò)濾器的格式如上、必須包含 "pattern"呐伞、"type"敌卓、"replacement" 三個(gè)字段。其中 pattern 定義的是滿(mǎn)足替換的格式伶氢,type 則定義為格式替換類(lèi)型趟径。replacement 則是對(duì)于滿(mǎn)足格式的字符串瘪吏,要替換成的字符串。
2)分詞器
常用的分詞器有 standard蜗巧、keyword掌眠、whitespace、pattern等幕屹。
standard 分詞器將字符串分割成單獨(dú)的字詞蓝丙,刪除大部分標(biāo)點(diǎn)符號(hào)。keyword 分詞器輸出和它接收到的相同的字符串望拖,不做任何分詞處理渺尘。whitespace 分詞器只通過(guò)空格倆分割文本。pattern 分詞器可以通過(guò)正則表達(dá)式來(lái)分割文本靠娱。最常用的一般為 standard 分詞器沧烈。
更多的分詞器詳見(jiàn)官方文檔:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/analysis-standard-tokenizer.html
3)標(biāo)記過(guò)濾器
常用的標(biāo)記過(guò)濾器有 lowercase 和 stop 。lowercase 標(biāo)記過(guò)濾器將詞轉(zhuǎn)換為小寫(xiě)像云,stop 標(biāo)記過(guò)濾器用戶(hù)去除一些自定義停用詞或者是語(yǔ)言?xún)?nèi)定義的停用詞锌雀。
stop 標(biāo)記過(guò)濾器的常用結(jié)構(gòu)如下:
"filter": {
"my_stopwords": {
"type": "stop",
"stopwords": [ "the", "a" ]
}
}
上述標(biāo)記過(guò)濾器是自定義的過(guò)濾掉 "the" 、"a" 兩詞迅诬。除了自定義腋逆,還有特定的語(yǔ)言停用詞過(guò)濾,相應(yīng)的有:spanish 侈贷、english等惩歉。具體用法如下:
"filter": {
"my_stop": {
"type": "stop",
"stopwords": _spanish_
}
}
更多的語(yǔ)言停用詞參考官方網(wǎng)址:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/analysis-stop-tokenfilter.html/
4)分析器組合
如上定義了字符過(guò)濾器、分詞器俏蛮、標(biāo)記過(guò)濾器之后撑蚌,就該用戶(hù)自定義分析器。分析器是由三者按順序組合而成搏屑。
將上述組件組合起來(lái)便是:
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "&_to_and", "replace_dot" ],
"tokenizer": "standard",
"filter": [ "lowercase", "my_stopwords", "my_stop" ]
}
}
將自定義分析器各部分完整表示如下:
"settings": {
"index": {
"analysis": {
"char_filter": {
"&_to_and": {
"type": "mapping",
"mappings": [ "&=> and "]
},
"replace_dot": {
"pattern": "\\.",
"type": "pattern_replace",
"replacement": " "
}
},
"filter": {
"my_stop": {
"type": "stop",
"stopwords": _spanish_
},
"my_stopwords": {
"type": "stop",
"stopwords": [ "the", "a" ]
}
},
"analyzer": {
"my_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "&_to_and", "replace_dot" ],
"tokenizer": "standard",
"filter": [ "lowercase", "my_stopwords", "my_stop" ]
}
}
},
...
}
}
4争涌、索引類(lèi)型的字段映射
索引模板中,映射字段所對(duì)應(yīng)的常用結(jié)構(gòu)是:
"mappings": {
"my_type": { // 索引下的類(lèi)型 my_type 應(yīng)用該映射
"dynamic_templates": [ ... ], // 動(dòng)態(tài)映射部分辣恋,用于未定義的 my_type 下字段
"properties": { ... } // 自定義字段的響應(yīng)映射
}
}
"my_type" 是索引下的一個(gè)類(lèi)型亮垫,如果采用上述定義的索引模板,則索引下僅僅 my_type 類(lèi)型應(yīng)用了該索引模板伟骨。如果想要索引下的所有模板應(yīng)用定義的映射饮潦,則可以將 "my_type" 替換成 "default" 字段。
1)動(dòng)態(tài)映射
動(dòng)態(tài)映射 "dynamic_templates" 字段對(duì)應(yīng)的是一個(gè)數(shù)組携狭,數(shù)組中的元素是一個(gè)個(gè)字段的映射模板继蜡。每個(gè)字段的映射模板都有一個(gè)名字用戶(hù)描述這個(gè)模板的用途,一個(gè) mapping 字段由于指明這個(gè)映射如何使用,和至少一個(gè)參數(shù)(例如 match)來(lái)定義這個(gè)模板適用于哪個(gè)字段稀并。
dynamic_templates 字段對(duì)應(yīng)的字段模板結(jié)構(gòu)如下:
{
"string_fields": { // 字段映射模板的名稱(chēng)鲫剿,一般為"類(lèi)型_fields"的命名方式
"match": "*", // 匹配的字段名為所有
"match_mapping_type": "string", // 限制匹配的字段類(lèi)型,只能是 string 類(lèi)型
"mapping": { ... } // 字段的處理方式
}
如下為一個(gè)定義實(shí)例:
"mappings": {
"my_type": {
"dynamic_templates": [
{
"string_fields": { // 字段映射模板的名稱(chēng)稻轨,一般為"類(lèi)型_fields"的命名方式
"match": "*", // 匹配的字段名為所有
"match_mapping_type": "string", // 限制匹配的字段類(lèi)型,只能是 string 類(lèi)型
"mapping": {
"fielddata": { "format": "disabled" }, // fielddata 不可用雕凹,對(duì)于分析字段殴俱,其默認(rèn)值是可用
"analyzer": "only_words_analyzer", // 字段采用的分析器名,默認(rèn)值為 standard 分析器
"index": "analyzed", // 索引方式定義為索引枚抵,默認(rèn)值是分析
"omit_norms": true, // omit_norms 為真表示考慮字段的加權(quán)线欲,可分析字段默認(rèn)值 false
"type": "string", // 字段類(lèi)型限定為 string
"fields": { // 定義一個(gè)嵌套字段,將該字段應(yīng)用于不分析的場(chǎng)景
"raw": {
"ignore_above": 256, // 忽略字段對(duì)應(yīng)的值長(zhǎng)度大于256的字段
"index": "not_analyzed", // 索引方式為不分析
"type": "string", // 字段的類(lèi)型為 string
"doc_values": true // 對(duì)于不分析字段汽摹,doc_values 對(duì)應(yīng)的是一種列式存儲(chǔ)結(jié)構(gòu)李丰,默認(rèn)false
}
}
}
}
},
...
],
"properties": { ... }
}
}
可以看到逼泣,內(nèi)部的字段模板的 mapping 字段下包含 fielddata趴泌、analyzer、index拉庶、omit_norms嗜憔、type、fields 等六個(gè)字段氏仗,下面分別解釋這六個(gè)字段吉捶。
對(duì)于基本的 Elasticsearch 做個(gè)了解,一般的 es 用戶(hù)搜索字段皆尔,其反應(yīng)數(shù)據(jù)非衬盘颍快,接近實(shí)時(shí)慷蠕,這個(gè)效果得益于其倒排索引的數(shù)據(jù)結(jié)構(gòu)珊拼,然而倒排索引這個(gè)數(shù)據(jù)結(jié)構(gòu)在做聚合分析時(shí),卻不是那么容易砌们。因而在做傳統(tǒng)分析時(shí)杆麸,需要一種我們常見(jiàn)的行式存儲(chǔ)結(jié)構(gòu),這一結(jié)構(gòu)在排序和巨額和分析時(shí)浪感,具有明顯的優(yōu)勢(shì)昔头。這一部分詳見(jiàn) Elasticsearch 搜索與聚合在數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)方面的理解 。
fielddata 這一字段就是對(duì)于分析字段影兽,除了倒排索引的數(shù)據(jù)存儲(chǔ)方式揭斧,仍定義一種形式上看著是行式結(jié)構(gòu)的存儲(chǔ)樣式,數(shù)據(jù)存儲(chǔ)在內(nèi)存中,用于對(duì)字段的排序和聚合分析讹开。對(duì)于分析字段 fielddata 的默認(rèn)值是可用的盅视。如果確定一個(gè)分析字段不需要排序或者聚合分析,則該字段就設(shè)置為不可用旦万。這樣可以節(jié)省內(nèi)存闹击。
analyzer 定義的是該字段的分析器,默認(rèn)的分析器是 standard 標(biāo)準(zhǔn)分析器成艘,這個(gè)地方可定義為自定義的分析器赏半。
index 定義的是字段的索引方式。默認(rèn)的 淆两,Elasticsearch 對(duì)字段采取的是分析索引断箫,即會(huì)對(duì)字段進(jìn)行倒排索引。
omit_norms 定義的是字段在分析過(guò)程中秋冰,是否考慮加權(quán)仲义。例如如果權(quán)重為2,字段出現(xiàn)的頻率在計(jì)算時(shí)會(huì)翻倍剑勾,以提高計(jì)算的匹配度埃撵。對(duì)于分析字段,默認(rèn)的是不考慮加權(quán)甥材。
type 定義的是字段的數(shù)據(jù)類(lèi)型盯另。
fields 是字段應(yīng)以一個(gè)嵌入字段。以 title 字段為例洲赵,Elasticsearch 會(huì)自動(dòng)生成兩個(gè)字段鸳惯,分別是 title 和 title.raw 。這樣叠萍,在有可能同時(shí)需要分詞和不分詞結(jié)果的環(huán)境芝发,就可以很靈活的使用不同的索引字段。比如苛谷,查看標(biāo)題中最常用的單詞辅鲸,應(yīng)該是使用 title 字段,查看閱讀數(shù)最多的文章標(biāo)題腹殿,應(yīng)該是使用 title.raw 字段独悴。
ignore_above 字段是索引時(shí)忽略長(zhǎng)度超過(guò)定義值的字段。
doc_values 字段與 fielddata 相對(duì)應(yīng)锣尉,都是為了字段方便排序和聚合分析而重新定義的一種數(shù)據(jù)存儲(chǔ)方式刻炒,不同的是,fielddata 應(yīng)用于分析字段自沧,存儲(chǔ)在內(nèi)存中坟奥;doc_values 應(yīng)用于不分析字段,存儲(chǔ)于磁盤(pán)中。
上述是針對(duì)字段數(shù)據(jù)類(lèi)型為 string 的動(dòng)態(tài)模板定義爱谁,對(duì)于其他數(shù)據(jù)類(lèi)型晒喷,其動(dòng)態(tài)模板的定義方式一般如下:
{
"float_fields": { // 命名方式 "類(lèi)型_fields"
"match": "*",
"match_mapping_type": "float",
"mapping": {
"type": "float",
"doc_values": true // doc_values 定義為 true访敌,便于排序與聚合分析
}
}
}
2)自定義字段映射
針對(duì)索引類(lèi)型中存在的字段凉敲,除了可以采用動(dòng)態(tài)模板的方式,還可以采用定義定義的方式寺旺,常見(jiàn)的自定義結(jié)構(gòu)如下:
"mappings": {
"my_type": {
"dynamic_templates": [ ... ],
"properties": {
"user_city": { // 字段名
"analyzer": "lowercase_analyzer", // 字段分析器
"index": "analyzed", // 字段索引方式定義索引
"type": "string", // 字段數(shù)據(jù)類(lèi)型定義為 string
"fields": { // 定義一個(gè)名為 user_city.raw 的嵌入的不分析字段
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
}荡陷,
"money":{
"type": "double",
"doc_values": true
}
...
}
}
}
復(fù)雜一些的是 string 類(lèi)型的字段,對(duì)于其他類(lèi)型的字段迅涮,定義方式類(lèi)似于上述的 money 字段定義方式。
5徽龟、別名
即使你認(rèn)為現(xiàn)在的索引設(shè)計(jì)已經(jīng)是完美的了叮姑,當(dāng)你的應(yīng)用在生產(chǎn)環(huán)境使用時(shí),還是有可能在今后有一些改變的据悔。所以請(qǐng)做好準(zhǔn)備:在應(yīng)用中使用別名而不是索引传透。然后你就可以在任何時(shí)候重建索引。別名的開(kāi)銷(xiāo)很小极颓,應(yīng)當(dāng)廣泛使用朱盐。利用索引別名,可以實(shí)現(xiàn)零停機(jī)時(shí)間重新索引菠隆。
定義方式如下:
{
"order": 0, // 模板優(yōu)先級(jí)
"template": "sample_info*", // 模板匹配的名稱(chēng)方式
"settings": {...}, // 索引設(shè)置
"mappings": {...}, // 索引中各字段的映射定義
"aliases": {
"my_index":{}
}
}
零停機(jī)時(shí)間實(shí)現(xiàn)重新索引方式:
POST /_aliases
{
"actions": [
{ "remove": { "index": "my_index_v1", "alias": "my_index" }},
{ "add": { "index": "my_index_v2", "alias": "my_index" }}
]
}