elasticsearch 索引_Elasticsearch系列---索引管理
概要
Elasticsearch讓索引創(chuàng)建變得非常簡單,只要索引一條新的數(shù)據(jù),索引會自動創(chuàng)建出來,但隨著數(shù)據(jù)量的增加,我們開始有了索引優(yōu)化和搜索優(yōu)化的需求之后,就會發(fā)現(xiàn)自動創(chuàng)建的索引在某些方面不能非常完美的適應(yīng)我們的需求,我們開始考慮手動創(chuàng)建適合我們業(yè)務(wù)需求的索引。
索引的CRUD
為了更好地貼切我們的業(yè)務(wù)數(shù)據(jù)需求,我們開始更精細(xì)的管理我們的索引。
創(chuàng)建索引
創(chuàng)建索引的語法示例如下:
PUT /music {"settings": {"number_of_shards": 3,"number_of_replicas": 1},"mappings": {"children": {"properties": {"name": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}}}} }settings內(nèi)的參數(shù)
- numberofshards:每個索引的primary shard數(shù)量,索引創(chuàng)建后不可修改。
- numberofreplicas: 每個索引的replica shard的數(shù)量,可以隨時修改。
mappings內(nèi)的參數(shù)
- type: 6.3.1版本只允許設(shè)置一個type
- properties:類型映射具體信息,索引文檔的字段名稱,類型,分詞器都在里面指定。
默認(rèn)Elasticsearch是允許自動創(chuàng)建索引的,生產(chǎn)環(huán)境上為了避免自動索引可能出現(xiàn)的隱患,可以禁止自動創(chuàng)建索引,修改elasticsearch.yml配置文件即可:
action.auto_create_index: false
修改索引
可以單獨修改setting部分和mapping部分,修改setting部分示例如下:
PUT /music/_settings {"number_of_replicas": 2 }如果要修改mapping信息,如給索引新增字段length、likes、content,示例如下:
PUT /music/_mapping/children {"properties": {"length": {"type": "long"},"likes": {"type": "long"},"content": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}} }刪除索引
DELETE /music DELETE /music,content DELETE /music* DELETE /_all DELETE /*如上命令均可刪除索引,但此操作一定要慎重,反復(fù)確認(rèn)后再操作,誤刪的后果不可想像,建議刪除操作一定要設(shè)置操作權(quán)限,另外Elasticsearch可以設(shè)置只限定索引名稱進(jìn)行刪除,不允許通配符或_all刪除大量的索引,作如下設(shè)置即可:
action.destructive_requires_name: true
誤刪索引的后果非常嚴(yán)重,請在操作權(quán)限上加把鎖,寧可麻煩也不要誤刪。
查看索引信息
GET /music GET /music/_settings GET /music/_mapping三條命令可以查看索引的完整信息,只查setting信息,只查mapping信息。
分詞器設(shè)置
analysis是索引設(shè)置中非常重要的一部分,默認(rèn)的分詞器我們前面有介紹,有興趣可以翻一下。我們可以為索引單獨配置特有的分詞器,或者自定義分詞器。
修改分詞器設(shè)置
例如,我們?yōu)閙usic索引創(chuàng)建一個新的分詞器,叫做music_std,啟用英文停用詞列表:
PUT /music {"settings": {"analysis": {"analyzer": {"music_std": {"type": "standard","stopwords": "_english_"}}}} }此命令只能在創(chuàng)建時候執(zhí)行,已經(jīng)存在的索引執(zhí)行會報錯。
我們對music索引進(jìn)行分詞器測試:
GET /music/_analyze {"analyzer": "music_std","text": "get up brightly early in the morning" }測試結(jié)果是"in","the"這兩個詞已經(jīng)被正確的移除掉了。
自定義分詞器
Elasticsearch對分詞器的應(yīng)用設(shè)置得非常靈活,用戶可以根據(jù)自己的需求靈活定制字符過濾器、分詞器、詞單元過濾器來創(chuàng)建自定義的分詞器。
文檔的分詞過程包含以下幾步:
- 字符過濾器
對字符串進(jìn)行預(yù)處理,如HTML標(biāo)簽清洗Love --> Love,I & you --> I and you等等。
- 分詞器
把字符串切分成單個的詞條,如英文的按空格和標(biāo)點切分,中文的按詞語切分,針對不同的語言,有不同的分詞器,有相對簡單的標(biāo)準(zhǔn)分詞器,也有特別復(fù)雜的中文分詞器,里面包含了非常復(fù)雜的切分邏輯如:
I Love you --> I/Love/you
我和我的祖國 --> 我/和/我的/祖國
- Token過濾器
將分詞器得到的詞條進(jìn)一步的處理,如改變詞條(英文詞干提取loves --> love),刪除無實際意義的詞條(英文的a, and, this,中文的"的","了","嗎"),增加詞條(補(bǔ)充同義詞)
如果我們自定義分詞器,可以從這三個組件入手,可以自行替換。我們舉一個示例:
PUT /music {"settings": {"analysis": {"char_filter": {"&_to_and": {"type": "mapping","mappings": ["&=> and"]}},"filter": {"my_stopwords": {"type": "stop","stopwords": ["the", "a"]}},"analyzer": {"my_analyzer": {"type": "custom","char_filter": ["html_strip", "&_to_and"],"tokenizer": "standard","filter": ["lowercase", "my_stopwords"]}}}} }上面示例中我們自定義的分詞器有如下特點:
- 字符過濾器:把&轉(zhuǎn)換成and,并加上html_strip處理html文本
- token過濾器:將"the","a"作為停用詞,全部改成小寫
我們對這個分詞器進(jìn)行測試:
GET /music/_analyze {"text": "you & me the love, <a>, HAHA!!","analyzer": "my_analyzer" }響應(yīng)的結(jié)果:
{"tokens": [{"token": "you","start_offset": 0,"end_offset": 3,"type": "<ALPHANUM>","position": 0},{"token": "and","start_offset": 4,"end_offset": 5,"type": "<ALPHANUM>","position": 1},{"token": "me","start_offset": 6,"end_offset": 8,"type": "<ALPHANUM>","position": 2},{"token": "love","start_offset": 13,"end_offset": 17,"type": "<ALPHANUM>","position": 4},{"token": "haha","start_offset": 24,"end_offset": 28,"type": "<ALPHANUM>","position": 5}] }可以看到,"the"作為停用詞被移除了,&變成了"and",html標(biāo)簽移除了,HAHA小寫處理后得到haha。
自定義分詞器后,如果需要應(yīng)用在索引上,需要將它綁定到具體的字段上:
PUT /music/_mapping/children {"properties": {"content": {"type": "text","analyzer": "my_analyzer"}} }后面只要有新的文檔進(jìn)行索引,在content字段上都會使用我們自定義的分詞器。
映射對象
root object
映射對象信息是一組JSON結(jié)構(gòu),最頂層的叫根對象(root object),包括內(nèi)容如下:
- properties: 索引中每個字段的映射信息。
- metadata:各種元數(shù)據(jù)信息,以下劃線開頭,如id,source,_type。
- settings:設(shè)置項信息,如analyzer。
- 其他settings:比如includeinall
properties
主要是指文檔字段和屬性最重要的三個設(shè)置:
- type: 數(shù)據(jù)類型,如text、date、long等。
- index: 該字段是否需要全文搜索(analyzed),或精準(zhǔn)搜索(not_analyzed)或是不支持搜索(no)。
- analyzer: 文檔索引和搜索時的分詞器。
例如節(jié)選了以下properties信息:
{"music": {"mappings": {"children": {"properties": {"author": {"type": "text","analyzer": "english"}}}}} }_source
source字段存儲的內(nèi)容包含文檔的JSON字符串,source字段在寫入磁盤前會被壓縮。
_source存儲的內(nèi)容才是我們真正關(guān)心的數(shù)據(jù),我們可以更加方便的完成這些事:
- 查詢的時候可以一次性拿到完整的document,不需要先拿document id,再發(fā)送一次請求拿document
- partial update基于_source實現(xiàn)
- reindex時,直接基于_source實現(xiàn),不需要從數(shù)據(jù)庫(或者其他外部存儲)查詢數(shù)據(jù)再修改
- 可以基于_source定制返回field
- debug query更容易,因為可以直接看到_source
_all
建立索引時將所有field拼接在一起,作為一個all field ,沒指定任何field進(jìn)行搜索時,就是搜索all field,一般輕量搜索中用得比較多。
如果不需要_all field,可以設(shè)置成禁用:
PUT /music/_mapping/children {"_all": {"enabled": false} }也可以指定某些field不加入_all field
PUT /music/_mapping/children {"properties": {"author": {"type": "text","include_in_all": false}} }metadata
文檔標(biāo)識主要的幾個字段:
- _id:文檔ID
- _type:類型名稱,6.x以后一個索引只會有一個type
- _index: 文檔所在的索引名稱
這三個字段是用來標(biāo)識一個獨一無二的文檔所在的位置信息,從這三個字段我們基本上可以定位出來該文檔存儲在哪個shard中。
動態(tài)映射
dynamic屬性
Elasticsearch索引文檔時,如果JSON結(jié)構(gòu)出現(xiàn)新的字段,Elasticsearch會根據(jù)dynamic mapping規(guī)則來識別字段的數(shù)據(jù)類型,并自動增加新的字段,如果我們對文檔的JSON結(jié)構(gòu)有較嚴(yán)格的規(guī)定,這種自動增加字段的行為,就不是我們期望的操作,我們可以為properties設(shè)置dynamic屬性來決定這種行為:
- true: 動態(tài)添加新的字段
- false:忽略新的字段
- strict: 遇到新的字段,拋出異常
這個dynamic參數(shù)可以在任何一層的object中使用,如:
PUT /music {"mappings": {"children": {"dynamic": "strict","properties": {"name": {"type": "text"},"address": {"type": "object","dynamic": "true"}}}} }如果children下面遇到新字段,就會拋出異常如果address內(nèi)部對象中遇到新字段,會動態(tài)創(chuàng)建該字段
示例:
# address內(nèi)部對象增加兩個新字段 PUT /music/children/1 {"name":"sunshine","address": {"province": "gd","city": "sz"} }創(chuàng)建成功,響應(yīng)如下:
{"_index": "music","_type": "children","_id": "1","_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 0,"_primary_term": 1 } # children下直接增加新字段author PUT /music/children/1 {"name":"sunshine","author":"Johnny Cash" }創(chuàng)建失敗,報錯響應(yīng)如下:
{"error": {"root_cause": [{"type": "strict_dynamic_mapping_exception","reason": "mapping set to strict, dynamic introduction of [author] within [children] is not allowed"}],"type": "strict_dynamic_mapping_exception","reason": "mapping set to strict, dynamic introduction of [author] within [children] is not allowed"},"status": 400 }定制dynamic mapping策略
Elasticsearch在運(yùn)行中遇到新增的字段時,會根據(jù)動態(tài)映射模板為新的字段定義類型,但字段類型是根據(jù)首次遇到的字段值來定義的,可能會出現(xiàn)誤判的情況。
我們先舉一個反例,假設(shè)我們有一個新增的字段remark,里面的內(nèi)容是"2019-12-17",是一個日期格式的內(nèi)容,Elasticsearch會把這個note字段設(shè)置成日期格式,但remark字段第二條數(shù)據(jù)過來的卻是"Comment Submit",這只是一段文本,remark字段已經(jīng)是日期格式了,第二條保存就會拋出異常。
針對日期檢測,我們可以選擇關(guān)閉,如下:
PUT /music {"mappings": {"children": {"date_detection": false}} }但我們針對Long類型,Boolean類型的,同樣有這種情況,逐一關(guān)閉可行性不高,為此我們需要使用動態(tài)模板配置。
動態(tài)模板
使用動態(tài)模板(dynamic template),我們可以通過字段名稱或數(shù)據(jù)類型來應(yīng)用不同的映射,來定制自己的模板。
例如我們使用字段名稱后綴的方式:
PUT /music {"mappings": {"children": {"dynamic_templates": [{ "en": {"match": "*_en", "match_mapping_type": "string","mapping": {"type": "text","analyzer": "english"}}}]}} }這個含義是如果字段以_en結(jié)尾,那么類型為text,analyzer為english,否則類型為string,analyzer為standard。
測試內(nèi)容:
PUT /music/children/1 {"content": "you are my sunshine" }PUT /music/children/2 {"content_en": "you are my sunshine" }理論上content使用standard分詞器,4個單詞均可被索引到,content_en字段使用english分詞器,are作為停用詞會被移除掉。
對索引進(jìn)行搜索可知:
GET /music/children/_search {"query": {"match": {"content_en": "are"}} }結(jié)果是空
{"took": 1,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 0,"max_score": null,"hits": []} }使用其他的關(guān)鍵詞,或使用content字段,搜索均能出結(jié)果,符合預(yù)期。
小建議以上只是動態(tài)映射模板的一個小案例,真實生產(chǎn)環(huán)境中文檔的復(fù)雜度遠(yuǎn)高于此,對文檔的結(jié)構(gòu)而言,優(yōu)先手動創(chuàng)建索引,明確每個字段的含義和數(shù)據(jù)類型,其次再做通用的動態(tài)映射模板,但也需要定時檢查索引下的數(shù)據(jù)類型,以防出現(xiàn)意外情況。
小結(jié)
本篇主要介紹索引的相關(guān)知識,包含索引的CRUD、自定義分詞器、映射對象的知識,最后簡單介紹了映射模板的配置,實際生產(chǎn)如果有乃至動態(tài)模板配置,肯定遠(yuǎn)比這個復(fù)雜,這里僅作拋磚引玉,謝謝。
專注Java高并發(fā)、分布式架構(gòu),更多技術(shù)干貨分享與心得,請關(guān)注公眾號:Java架構(gòu)社區(qū)
總結(jié)
以上是生活随笔為你收集整理的elasticsearch 索引_Elasticsearch系列---索引管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python批处理文件_Python文件
- 下一篇: eslint 保存自动格式化_ESLin