理解 mapping 中的 null_value


導語



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源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章