導語
null 不能被索引或搜索。當字段設置爲 null(或空數組或 所有值爲 null 值的數組)時,將其視爲該字段沒有值。使用 null_value 參數可以用指定的值替換顯式的空值,以便可以對其進行索引和搜索。
例子一
PUT my-index-000001
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword",
"null_value": "NULL"
}
}
}
}
在上面,我們針對 status_code 字段定義其 null_value,也就是說當我們導入一個文檔,當它的 status_code 指定爲 null 時,那麼在導入時,實際上它是被認爲是 status_code 當做 "NULL" 被導入並進行分析。我們以下面的兩個文檔來進行說明:
PUT my-index-000001/_doc/1
{
"status_code": null
}
PUT my-index-000001/_doc/2
{
"status_code": []
}
使用上面的兩個命令寫入兩個文檔到索引 my-index-000001 中。我們執行如下的搜索:
GET my-index-000001/_search
我們可以搜索到兩個文檔:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"status_code" : null
}
},
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"status_code" : [ ]
}
}
]
}
}
這顯然是正確的,因爲我們導入了兩個文檔。我們接着進行如下的搜索:
GET my-index-000001/_search
{
"query": {
"term": {
"status_code": "NULL"
}
}
}
上面的命令顯示的結果爲:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.2876821,
"_source" : {
"status_code" : null
}
}
]
}
}
顯然,第一個文檔被搜索到,而第二個文檔沒有被搜索到。這是因爲在第一個文檔中,它清楚地指出 "status_code": null,所以在導入文檔時,null_value 被認爲是 status_code 而被導入並進行分析。第二個文檔沒有指定它是 null,所以沒有被搜索出來。
例子二
假如我們有一下兩個文檔:
PUT twitter/_doc/1
{
"age": null
}
PUT twitter/_doc/2
{
"age": 20
}
在上面,我們有兩個文檔。第一個文檔的 age 值爲 null,也就是說它不能被搜索到。假如我們做如下的聚合:
GET twitter/_search
{
"size": 0,
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
那麼上面的聚合返回:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg_age" : {
"value" : 20.0
}
}
}
也就是說平均年齡是 20 歲,這是因爲第一個文檔被視爲不見。我們怎麼才能讓第一個文檔也參入聚合呢?我們可以使用 null_value 來爲 null 值的字段設置一個值。我們修改 mapping 爲:
DELETE twitter
PUT twitter
{
"mappings": {
"properties": {
"age": {
"type": "float",
"null_value": 0
}
}
}
}
我們再重新導入之前的兩個文檔:
PUT twitter/_doc/1
{
"age": null
}
PUT twitter/_doc/2
{
"age": 20
}
由於我們已經定義當 age 爲 null 時,null_value 將會起作用,它的值將爲 0,那麼這個文檔將爲可見。執行如下的聚合:
GET twitter/_search
{
"size": 0,
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
上面的結果爲:
{
"took" : 703,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg_age" : {
"value" : 10.0
}
}
}
現在的平均值變爲 10 了,也就是 (20 + 0)/2 = 10。
這裏必須注意的是,我們必須顯示地指定 age 爲 null,否則 null_vale 將不會起任何的作用。比如:
DELETE twitter
PUT twitter
{
"mappings": {
"properties": {
"age": {
"type": "float",
"null_value": 0
}
}
}
}
PUT twitter/_doc/1
{
"content": "This is cool"
}
PUT twitter/_doc/2
{
"age": 20,
"content": "This is cool too!"
}
在上面,第一個文檔裏沒有定義 age,那麼 null_value 將不會起作用。如果我們做如下的聚合:
GET twitter/_search
{
"size": 0,
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
其顯示結果爲:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"avg_age" : {
"value" : 20.0
}
}
}
也就是說第一個文檔沒有被搜索到。
正文完
作者:劉曉國
本文編輯:喝咖啡的貓
嗨,互動起來吧!
喜歡這篇文章麼?
歡迎留下你想說的,留言 100% 精選哦!
Elastic 社區公衆號長期徵稿,如果您有 Elastic 技術的相關文章,也歡迎投稿至本公衆號,一起進步! 投稿請添加微信:medcl123
招聘信息
Job board
社區招聘欄目是一個新的嘗試,幫助社區的小夥伴找到心儀的職位,也幫助企業找到所需的人才,爲伯樂和千里馬牽線搭橋。有招聘需求的企業和正在求職的社區小夥伴,可以聯繫微信 medcl123 提交招聘需求和發佈個人簡歷信息。
關
注
我
們
Elastic中文社區公衆號 (elastic-cn)
爲您彙集 Elastic 社區的最新動態、精選乾貨文章、精華討論、文檔資料、翻譯與版本發佈等。
喜歡本篇內容就請給我們點個[在看]吧
本文分享自微信公衆號 - Elastic中文社區(elastic-cn)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。