Elasticsearch 設(shè)置默認(rèn)值的三種方式
1、實(shí)戰(zhàn)問題
在使用 Elasticsearch 過程中,不免還會(huì)有 Mysql 等關(guān)系型數(shù)據(jù)庫的使用痕跡,以下兩個(gè)都是實(shí)戰(zhàn)開發(fā)問到的問題:
Elasticsearch 新增字段,能在 Mapping 設(shè)置默認(rèn)值嗎?
Elasticsearch 有什么好的方式維護(hù)文檔的 create_time (創(chuàng)建時(shí)間)和 update_time (更新時(shí)間)嗎?
本文就從 Elasticsearch 默認(rèn)值的實(shí)現(xiàn)方案說開去。
2、Elasticsearch Mapping 層面默認(rèn)值
認(rèn)知前提:嚴(yán)格講 Elasticsearch 是不支持 Mapping 層面設(shè)置數(shù)據(jù)類型的時(shí)候,設(shè)置字段的默認(rèn)值的。
有人會(huì)說,null value 設(shè)置算不算?不算。
大家看一下:
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword",
"null_value": "NULL"
}
}
}
}
null_value 的本質(zhì)是將“NULL” 替換 null 值,以使得空值可被索引或者檢索。
我們期望設(shè)置 Mapping 的時(shí)候,可以對各種數(shù)據(jù)類型添加一個(gè)任意指定的缺省值。但是 Elasticsearch Mapping 層面不支持,咋辦?
只能去尋找其他的方案。
3、曲線救國實(shí)現(xiàn) Elasticsearch 設(shè)置默認(rèn)值
直接給出答案,共三種設(shè)置默認(rèn)值的。
3.1 方案 一:pipeline 設(shè)置默認(rèn)值
# 創(chuàng)建 append 管道
PUT _ingest/pipeline/add_default_pipeline
{
"processors": [
{
"set": {
"field": "sale_count",
"value": 1
}
}
]
}
# 創(chuàng)建索引
PUT customer
{
"mappings":{
"properties":{
"sale_count":{
"type":"integer"
},
"major":{
"type":"keyword",
"null_value": "NULL"
}
}
},
"settings": {
"index":{
"default_pipeline":"add_default_pipeline"
}
}
}
插入數(shù)據(jù),驗(yàn)證一把:
POST customer/_doc/1
{
"major":null
}
返回結(jié)果:
"max_score" : 1.0,
"hits" : [
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"major" : null,
"sale_count" : 1
}
}
]
}
以上的方式,實(shí)現(xiàn)了sale_count 的默認(rèn)值為1 的設(shè)置。
是借助索引設(shè)計(jì)層面在 setting 中關(guān)聯(lián) default_pipeline 實(shí)現(xiàn)的。
實(shí)現(xiàn)方式相對簡單,能保證用戶在設(shè)置索引的前提下,用戶只關(guān)注寫入數(shù)據(jù),其他后臺(tái)預(yù)處理管道幫助實(shí)現(xiàn)細(xì)節(jié)。
引申一下,針對開篇提到的第二個(gè)問題:
create_time 借助 pipeline 管道預(yù)處理 set processor 實(shí)現(xiàn)即可。
PUT _ingest/pipeline/create_time_pipeline
{
"description": "Adds create_time timestamp to documents",
"processors": [
{
"set": {
"field": "_source.create_time",
"value": "{{_ingest.timestamp}}"
}
}
]
}
DELETE my_index_0003
PUT my_index_0003
{
"settings": {
"index.default_pipeline": "create_time_pipeline"
}
}
POST my_index_0003/_doc/1
{}
GET my_index_0003/_search
update_time 自己維護(hù)更新,業(yè)務(wù)更新的時(shí)刻通過代碼或者腳本加上時(shí)間戳就可以。
3.2 方案 二:update_by_query 通過更新添加默認(rèn)值
POST customer/_doc/2
{
"major":null
}
# 批量更新腳本
POST customer/_update_by_query
{
"script": {
"lang": "painless",
"source": "if (ctx._source.major == null) {ctx._source.major = 'student'}"
}
}
POST customer/_search
結(jié)果是:
所有 major 為 null 的,都實(shí)現(xiàn)了更新,設(shè)置成了:“student"。

該方式屬于先寫入數(shù)據(jù),然后實(shí)現(xiàn)數(shù)據(jù)層面的更新,算作設(shè)置默認(rèn)值甚至都有點(diǎn)勉強(qiáng)。
3.3 方案 三:借助 pipeline script 更新
PUT _ingest/pipeline/update_pipeline
{
"processors": [
{
"script": {
"lang": "painless",
"source": """
if (ctx['major'] == null) {ctx['major'] = 'student'}
"""
}
}
]
}
POST customer/_doc/4
{
"major":null
}
POST customer/_update_by_query?pipeline=update_pipeline
{
"query": {
"match_all": {}
}
}
結(jié)果是:同方案二,也實(shí)現(xiàn)了更新。
該方案是第二種方案的內(nèi)卷版本,本質(zhì)實(shí)現(xiàn)基本一致。
強(qiáng)調(diào)細(xì)節(jié)不同點(diǎn),ctx 取值的時(shí)候,細(xì)節(jié)語法不一樣:
腳本script 操作,訪問方式:ctx._source.major。 pipeline 預(yù)處理腳本操作:訪問方式:ctx['major'] 。
4、小結(jié)
本文講解了 Elasticsearch 實(shí)現(xiàn)類關(guān)系型數(shù)據(jù)庫默認(rèn)值的三種方案,只有第一種屬于前置設(shè)置默認(rèn)值。
后兩種都是先寫入后設(shè)置默認(rèn)值的腳本更新實(shí)現(xiàn)方案。實(shí)戰(zhàn)方案選型,推薦方案一。
推薦

