免费xxxx大片国产片_精品在线一区_亚洲午夜福利av_亚洲色大成人一区二区_无码熟妇人妻AV在线影片免费

您的位置:首頁(yè) >城市 >

Elasticsearch Mapping類(lèi)型修改

2023-08-25 01:50:27 來(lái)源:博客園
背景

通常數(shù)據(jù)庫(kù)進(jìn)行分庫(kù)分表后,目前比較常規(guī)的作法,是通過(guò)將數(shù)據(jù)異構(gòu)到Elasticsearch來(lái)提供分頁(yè)列表查詢(xún)服務(wù);在創(chuàng)建Elasticsearch索引時(shí),基本都是會(huì)參考目前的業(yè)務(wù)需求、關(guān)系數(shù)據(jù)庫(kù)中的類(lèi)型以及對(duì)數(shù)據(jù)的相關(guān)規(guī)劃來(lái)定義相關(guān)字段mapping的類(lèi)型.在Elasticsearch的mapping中的列(或則叫屬性),有幾個(gè)比較重要的參數(shù)(更多參數(shù)參考官方文檔)

列類(lèi)型:type


【資料圖】

指定了該列的數(shù)據(jù)類(lèi)型,常用的有text,keyword,date,long,double,boolean以及objectnested,不同的類(lèi)型也有對(duì)應(yīng)的不同查詢(xún)方式,創(chuàng)建之后是不能修改的;

是否可索引:index

index選項(xiàng)控制字段值是否被索引。它接受trueorfalse,并且默認(rèn)為true. 未索引的字段不可查詢(xún),當(dāng)然也不能做為排序字段。

但是在實(shí)際的開(kāi)發(fā)過(guò)程中,又會(huì)有需求對(duì)現(xiàn)有的mapping的type進(jìn)行修改(類(lèi)似對(duì)MySQL數(shù)據(jù)表的字段進(jìn)行DDL操作)的訴求。比如商品上的價(jià)格price字段,按原來(lái)的業(yè)務(wù)分析,只需要提供數(shù)據(jù)返回即可,在創(chuàng)建索引時(shí)類(lèi)型定義了keyword了,并且index設(shè)置成了false,這時(shí)我們需要根據(jù)價(jià)格的范圍查詢(xún)或則進(jìn)行排序操作,就希望對(duì)mapping進(jìn)行調(diào)整,將類(lèi)型修改成數(shù)字類(lèi)型,索引也需要加上;今天針對(duì)Elasticsearch的Mapping類(lèi)型進(jìn)行修改,討論幾個(gè)可行的方案

方案1:運(yùn)用reindex

遇到問(wèn)題第一時(shí)間,我們應(yīng)該是查詢(xún)官方文檔是否有相關(guān)的操作說(shuō)明,在官方文檔中,確實(shí)還能找到對(duì)已有mapping更新的相關(guān)apiput-mapping,通過(guò)這個(gè)文檔,很快可以找到文檔中對(duì)修改已有mapping的列的方式(參考官方文檔),同時(shí)也提到的通過(guò)reindex的方式來(lái)修改已有類(lèi)型的方式;

除了支持的mapping parameters外,您不能更改現(xiàn)有字段的映射或字段類(lèi)型。更改現(xiàn)有字段可能會(huì)使已編制索引的數(shù)據(jù)無(wú)效。如果您需要更改字段的映射,請(qǐng)使用正確的映射創(chuàng)建一個(gè)新索引并將您的數(shù)據(jù)重新索引reindex到該索引中。

如原來(lái)索引的mapping如下

PUT /users{  "mappings" : {    "properties": {      "user_id": {        "type": "long"      }    }  }}//加一了兩條數(shù)據(jù)POST /users/_doc?refresh=wait_for{    "user_id" : 12345}POST /users/_doc?refresh=wait_for{    "user_id" : 12346}

這時(shí)想修改user_id的類(lèi)型為keyword,我們直接是修改不了的。

//嘗試直接修改type,行不通,會(huì)報(bào)錯(cuò)PUT /users/_mapping{    "properties": {        "user_id": {            "type": "keyword"        }    }}//報(bào)錯(cuò)信息{  "error": {    "root_cause": [      {        "type": "illegal_argument_exception",        "reason": "mapper [user_id] of different type, current_type [long], merged_type [keyword]"      }    ],    "type": "illegal_argument_exception",    "reason": "mapper [user_id] of different type, current_type [long], merged_type [keyword]"  },  "status": 400}

按官方文檔說(shuō)的reindex重新索引可按以下步驟操作

操作步驟第一步:創(chuàng)建新的索引new_usersuser_id的類(lèi)型定義成keyword
PUT /new_users{  "mappings" : {    "properties": {      "user_id": {        "type": "keyword"      }    }  }}
第二步:將原user索引標(biāo)記為只讀

控制我們的應(yīng)用系統(tǒng),數(shù)據(jù)停寫(xiě)不再向老索引中寫(xiě)數(shù)據(jù),并且最好對(duì)老索引進(jìn)行只讀操作設(shè)置,保證在reindex的過(guò)程中,不要生產(chǎn)新數(shù)據(jù),導(dǎo)致新老索數(shù)據(jù)不一致;

//設(shè)置索引為讀寫(xiě)的PUT /users/_settings{  "settings": {    "index.blocks.write": true  }}
第三步:將原user索引中的數(shù)據(jù)遷移到new_users
POST /_reindex{  "source": {    "index": "users"  },  "dest": {    "index": "new_users"  }}

reindex還有很多的參數(shù)可以配置,包括從遠(yuǎn)程的一個(gè)集群遷移數(shù)據(jù)都是可以的,詳細(xì)可參考:Reindex API

如果新的索引的mapping的定義與原索引的定義有差異的,會(huì)按新索引定義的dynamic規(guī)則進(jìn)行數(shù)據(jù)的遷移,具體的,可以參考:dynamic

dynamic設(shè)置控制是否可以動(dòng)態(tài)添加新字段。它接受三種設(shè)置:

說(shuō)明
true新檢測(cè)到的字段被添加到映射中。(默認(rèn)); 新增的數(shù)據(jù)類(lèi)型的規(guī)則,可以參考:dynamic-mapping
false忽略新檢測(cè)到的字段。這些字段不會(huì)被編入索引,因此將無(wú)法搜索,但仍會(huì)出現(xiàn)在_source返回的命中字段中。這些字段不會(huì)添加到映射中,必須明確添加新字段。
strict如果檢測(cè)到新字段,則會(huì)拋出異常并拒絕文檔。必須將新字段顯式添加到映射中。

同時(shí)將原user索引標(biāo)記為可讀寫(xiě)

//設(shè)置索引為可讀寫(xiě)PUT /users/_settings{  "settings": {    "index.blocks.write": false  }}
第四步:切換到使用新的mapping可以將應(yīng)用系統(tǒng)中的配置改成新索引也可以通過(guò)索引的別名的方式為新索引增加原來(lái)老索引的別名來(lái)操作,為索引增加別名參考文檔:Add index alias API,在增加別名前,需要?jiǎng)h除原來(lái)的老索引;
//為索引增加別名 基本格式PUT //_alias/POST //_alias///為new_users索引增加別名usersPUT /new_users/_alias/users//沒(méi)有刪除老索引前,是增加不了別名的,需要先刪除老別名{  "error": {    "root_cause": [      {        "type": "invalid_alias_name_exception",        "reason": "Invalid alias name [users], an index exists with the same name as the alias",        "index_uuid": "8Rbq_32BTHC4CoO_CqWdXA",        "index": "users"      }    ],    "type": "invalid_alias_name_exception",    "reason": "Invalid alias name [users], an index exists with the same name as the alias",    "index_uuid": "8Rbq_32BTHC4CoO_CqWdXA",    "index": "users"  },  "status": 400}
方案優(yōu)劣分析【優(yōu)點(diǎn)】操作簡(jiǎn)單,官方方案

該方案,不需要對(duì)原索引做操作,在線即可進(jìn)行,并且操作步驟也簡(jiǎn)單;也是官方文檔提供的方案。

【缺點(diǎn)】數(shù)據(jù)量大遷移耗時(shí)長(zhǎng)

當(dāng)數(shù)據(jù)最大時(shí),這個(gè)數(shù)據(jù)遷移會(huì)比較耗時(shí)

結(jié)論

當(dāng)數(shù)據(jù)量小時(shí),并且希望mapping比較規(guī)整好看,該方案是比較推薦的。當(dāng)數(shù)據(jù)量大時(shí),可能該方案在數(shù)據(jù)遷移過(guò)程中會(huì)比較耗時(shí),需要評(píng)估是否可行;

方案2:運(yùn)用multi-fields

為不同的目的以不同的方式索引同一個(gè)字段通常很有用。這就是multi-fields的目的。例如,一個(gè)string字段可以映射為text用于全文搜索的字段,也可以映射keyword為用于排序或聚合的字段;在這個(gè)方案中,應(yīng)用的是mapping參數(shù)fields來(lái)對(duì)同一個(gè)列,定義多種數(shù)據(jù)類(lèi)型;詳細(xì)[【官方文檔】multi-fields] (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/multi-fields.html)

操作步驟第一步:為列增加fields屬性

還是以上面的users這個(gè)索引為例,我們還是想將user_id的類(lèi)型定義成keyword;

PUT /users/_mapping{    "properties":{        "user_id":{            "type":"long",            "fields":{                "raw":{                    "type":"keyword"                }            }        }    }}

操作完成后,在usersuser_id列下,就會(huì)多出一個(gè)raw的子屬性;在我們正常寫(xiě)數(shù)據(jù)user_id時(shí),會(huì)自動(dòng)生成這兩個(gè)索引,一個(gè)是long類(lèi)型的user_id,以及keyword類(lèi)型的user_id.raw(注意這里有個(gè)點(diǎn),跟子對(duì)象訪問(wèn)方式一樣);在put mapping時(shí),type參數(shù)必需給,并且需要跟原來(lái)的類(lèi)型一致,fields中新定義的子屬性可以多個(gè);

【可選】第二步:歷史數(shù)據(jù)更新

針對(duì)歷史數(shù)據(jù)需要處理,可以借助_update_by_query來(lái)更新數(shù)據(jù),只需要將原來(lái)的索引再寫(xiě)一次,即可將新加的字段寫(xiě)入數(shù)據(jù)。

POST /users/_update_by_query {   "query":{       "exists":{           "field":"user_id"       }   },   "script":{       "source":"ctx._source.user_id=ctx._source.user_id ",       "lang":"painless"   }}// query 部分為需要更新數(shù)據(jù)過(guò)濾條件,可根據(jù)業(yè)務(wù)規(guī)則寫(xiě)// script 更數(shù)據(jù)的邏輯,這個(gè)基本可以不改
方案優(yōu)劣分析【優(yōu)點(diǎn)】不影響原索引,同一列可以定義多種類(lèi)型

通過(guò)這方式不會(huì)影響原來(lái)的索引數(shù)據(jù),可以不用修改現(xiàn)在的應(yīng)用程序的讀寫(xiě)方式,對(duì)應(yīng)用程序一切按原來(lái)邏輯執(zhí)行,對(duì)應(yīng)用方無(wú)感知,非常優(yōu)化。只需要有使用新類(lèi)型的場(chǎng)景使用即可,可以說(shuō)影響是最小的;同時(shí)只是做了一個(gè)定義,執(zhí)行速度是非??斓?,對(duì)Elasticsearch服務(wù)基本不會(huì)有太大影響;并且對(duì)于同一個(gè)列可以定義多個(gè)類(lèi)型,比如商品名稱(chēng),在多國(guó)多語(yǔ)言環(huán)境下可以根據(jù)不同語(yǔ)言定義多個(gè)列,對(duì)應(yīng)使用不同的分詞器;

【缺點(diǎn)】老數(shù)據(jù)不會(huì)自動(dòng)創(chuàng)建子索引,多出額外的存儲(chǔ)

老數(shù)據(jù)不會(huì)自動(dòng)創(chuàng)建索引,因?yàn)樾枰喑鲂碌乃饕齺?lái),會(huì)增加額外的存儲(chǔ);

結(jié)論

1、需要對(duì)多一列創(chuàng)建多個(gè)索引類(lèi)型時(shí),是一個(gè)非常推薦的方案;2、對(duì)于新索引,只有新業(yè)務(wù)使用,對(duì)老數(shù)據(jù)沒(méi)有訴求的,也非常推薦該方案;

方案3:運(yùn)用copy_to

copy_to是將多個(gè)字段的值,合并到一個(gè)字段中,便于搜索。但是也可以實(shí)現(xiàn)一個(gè)字段存在多個(gè)類(lèi)型的需求。詳細(xì)參考【官方文檔】copy_to

操作步驟

還是用上面的users這個(gè)索引為例,為user_id創(chuàng)建一個(gè)copy列:user_id_raw類(lèi)型定義成keyword

PUT /users/_mapping{    "properties":{        "user_id_raw":{          "type":"keyword",          "copy_to":"user_id"        }    }}

這個(gè)方案與方案2:multi-fields基本是一樣的,只是創(chuàng)建列的方式不同,優(yōu)缺點(diǎn)都一樣;

參考資料[1]【官方文檔】Mapping parameters[2]【官方文檔】Mapping Field datatypes[3] [【官方文檔】multi-fields] (https://www.elastic.co/guide/en/elasticsearch/reference/7.5/multi-fields.html)[4]Elasticsearch Rename Index[5]elasticSearch7.x—mapping中的fields屬性||copy_to配置(同一個(gè)字段兩種類(lèi)型)[6]《Elasticsearch:權(quán)威指南》Mapping -- Mapping parameters -- fields(multi-fields)

作者:京東零售 周德東

來(lái)源:京東云開(kāi)發(fā)者社區(qū) 轉(zhuǎn)載請(qǐng)注明來(lái)源

關(guān)鍵詞: