1、引言
實戰業務場景中,經常會遇到定義空值、檢索指定空值資料的情況,
這時候,當我們翻看官方檔案 null_value 部分,會看到如下的描述:
Accepts a string value which is substituted for any explicit null values. Defaults to null, which means the field is treated as missing.
接受一個字串值替換所有顯式的空值,默認為null,這意味著該欄位被視為丟失,
A null value cannot be indexed or searched. When a field is set to null, (or an empty array or an array of null values) it is treated as though that field has no values.
空值不能被索引或搜索,當欄位設定為null(或空陣列或 null 值的陣列)時,將其視為該欄位沒有值,
光看字面意思,你是不是感覺不好理解?
好吧,死磕一把,探個究竟:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword"
},
"title": {
"type": "text"
}
}
}
}
PUT my-index-000001/_bulk
{"index":{"_id":1}}
{"status_code":null,"title":"just test"}
{"index":{"_id":2}}
{"status_code":"","title":"just test"}
{"index":{"_id":3}}
{"status_code":[],"title":"just test"}
POST my-index-000001/_search
POST my-index-000001/_search
{
"query": {
"term": {
"status_code": null
}
}
}
如上檢索回傳錯誤如下:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "field name is null or empty"
}
],
"type": "illegal_argument_exception",
"reason": "field name is null or empty"
},
"status": 400
}
2、null_value 的含義
The null_value parameter allows you to replace explicit null values with the specified value so that it can be indexed and searched.
使用 null_value 引數可以用指定的值替換顯式的空值,以便可以對其進行索引和搜索,例如:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword",
"null_value": "NULL"
}
}
}
}
PUT my-index-000001/_bulk
{"index":{"_id":1}}
{"status_code":null}
{"index":{"_id":2}}
{"status_code":[]}
{"index":{"_id":3}}
{"status_code":"NULL"}
GET my-index-000001/_search
{
"query": {
"term": {
"status_code": "NULL"
}
}
}
注意,這里回傳結果:包含 _id = 1 以及 _id =3 的檔案,不包含_id = 2 的檔案,
說明一下:
"null_value": "NULL" 的含義:用指定的值替換顯式的空值,“NULL”可以自定義,比如業務系統中我們可以定義成“Unkown”,
大家能看懂的大白話解釋如下:
相當于我們在 Mapping 定義階段指定了空的默認值,用“NULL”來代替,這樣做的好處:類似如上的_id = 1 的檔案,空欄位也可以被索引、檢索,
不會再報 "field name is null or empty" 的錯誤了,
3、null_value 使用注意
null_value 必須和定義的資料型別匹配,舉例:long 型別欄位不能有string 型別的 null value,
如下的定義就會報錯:
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword"
},
"title": {
"type": "long",
"null_value": "NULL"
}
}
}
}
報錯如下:
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: For input string: \"NULL\""
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: For input string: \"NULL\"",
"caused_by": {
"type": "number_format_exception",
"reason": "For input string: \"NULL\""
}
},
"status": 400
}
解釋一下:明顯型別不匹配導致,
null_value 只影響了資料的索引,不會修改_source 檔案,
4、哪些欄位有null_value, 哪些欄位沒有null_value?
以下核心的常用欄位都支持:null_value,
Arrays
Boolean
Date
geo_point
IP
Keyword
Numeric
point
別問我怎么知道的,挨個翻查的官方檔案確認的,
最核心常問到的問題:
4.1 問題1:text 型別不支持 null_value 嗎?
是的,不支持,
來吧,實戰一把:
DELETE my-index-000001
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword"
},
"title": {
"type": "text",
"null_value": "NULL"
}
}
}
}
回傳結果如下:
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [title] has unsupported parameters: [null_value : NULL]"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: Mapping definition for [title] has unsupported parameters: [null_value : NULL]",
"caused_by": {
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [title] has unsupported parameters: [null_value : NULL]"
}
},
"status": 400
}
問題2:如果 text 型別也想設定空值,怎么搞呢?
推薦 multi-fields,借助 keyword 和 text 組合達到業務需求,
定義參考如下:
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword"
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"null_value": "NULL"
}
}
}
}
}
}
對于 text 型別的欄位,實戰業務場景下,我們經常會需要同時設定:multi_fields, 將 text 和 keyword 組合設定,
text 型別用于全文檢索,keyword用于聚合和排序,
同時,multi_fields 是 Elastic 認證工程師的核心考點之一,大家務必要掌握,
5、線上問題探討
老哥們,請教一個問題 ,我現在資料中有content這個欄位,我想查詢這個欄位不為空字串,我用must_not不行,我貼下我的sql
死磕 Elasticsearch 技術交流群
我的解讀如下:
說下這個問題正確寫法,以及之前寫法不對的原因,
判定是否為空,本質是:精準匹配問題,不是全文檢索的范疇(相似度匹配),所以選型使用:match_phrase 導致后面的錯誤,應該使用:term,
POST test_001/_search
{
"query": {
"bool": {
"filter": {
"bool": {
"must": [
{
"exists": {
"field": "cont"
}
},
{
"term": {
"content.keyword": {
"value": ""
}
}
}
]
}
}
}
}
}
注意:exists 檢索的含義是判定欄位是否存在,結合使用效果佳、更穩妥!
如下的腳本也可以實作,但由于性能問題,實際業務層面不推薦使用,
POST test_001/_search
{
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": "doc['content.keyword'].length == 1",
"lang": "painless"
}
}
}
}
}
}
試想一下,如果在定義 Mapping 的資料建模階段就定義了 text 和 keyword的組合 fields,并且:為keyword 設定了 null_value,這個問題就更好解決了,
6、小結
正如羅胖所說:再顯而易見的道理,在中國至少有一億人不知道,
而,我認為 Elasticsearch 技術也是,再顯而易見的技術點,在中國 Elastic 技術圈,至少有 N 多人不知道,
怎么辦?死磕一下,探個究竟吧!
你的業務場景怎么處理空值的呢?歡迎留言討論,
7、加餐-討論
有讀者私信留言:
其實老大也可以學習一下其他號,轉載一些大 V 或大公司的流量文章,圖文并茂的,雖然大家不一定看得懂,但看上去就很牛逼的樣子,給你的公號也能增粉,多好啊!你一周才1篇文章,大家都走了,
我的回復:
每個公眾號都有自己的使命和存在的價值,你可以仔細對比,每個號主都有自己的特點,為什么要趨同呢?我感覺這樣也很好(就是苦點、窮點),并且從長遠角度(十年甚至更長時間),堅持原創的價值才能體現,
加微信:elastic6(僅有少量坑位了),和 BAT 大佬一起精進 Elastic 技術!
推薦閱讀:
重磅 | 死磕 Elasticsearch 方法論認知清單(2020年國慶更新版)
能拿駕照就能通過 Elastic 認證考試!
更短時間更快習得更多干貨!
中國 近 50%+ Elastic 認證工程師出自于此!
和全球 800+ Elastic 愛好者一起死磕 Elasticsearch!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/223057.html
標籤:其他
上一篇:中國開源燃燒!Zilliz 獲全球開源基礎軟體最大單筆融資 4300 萬美元
下一篇:漫畫:你們這些奇葩的代碼!
