速看,ElasticSearch如何處理空值

大家好,我是咔咔 不期速成,日拱一卒

在MySQL中,十分不建議大家給表的默認值設置為Null,這個後期咔咔也會單獨出一期文章來說明這個事情。

但你進入一家新公司之前的業務中存在大量的字段默認值為Null,把這些值導入ElasticSearch中還是需要處理,接下來就看看ElasticSearch如何應對空值。

一、ElasticSearch如何處理Null值的

先看一個案例,當值為null時會發生什麼

POST /kaka/_bulk
"index": { "_id""1"}}
"tags" : ["search"]}  
"index": { "_id""2"}}
"tags" : ["search""open_source"] }  
"index": { "_id""3"}}
"tags" : null                      }  
"index": { "_id""4"}}
"tags" :"null"}

在這個案例中可以發現,第3、4都存在一個null值,不同的是一個為字符串null

post /kaka/_search
{
  "query":{
    "term": {
      "tags": null
    }
  },
  "profile":"true"
}

當你執行上面這搜索時會出現下面這個錯誤

{
  "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
}

然後咔咔就跑到ElasticSearch文檔找了一下原因,是因為在ElasticSearch中空值不能被索引或搜索,當字段值為null時、空數組、null值數組時,會將其視為該字段沒有值

若你執行的語句為如下,則會返回最後一條數據

post /kaka/_search
{
  "query":{
    "term": {
      "tags""null"
    }
  },
  "profile":"true"
}

二、使用exists解決ElasticSearch中Null值搜索問題

同樣在文檔中咔咔也找到了答案,案例如下

post /kaka/_search
{
  "query":{
    "constant_score": {
      "filter": {
        "missing": {
          "field""tags"
        }
      }
    }
  }
}

執行結果返回no [query] registered for [missing],這就讓人有點百思不得其解,再通過啃文檔後發現這個接口在ElasticSearch7.1已經被取消了,根據文檔的意思是exists可以同時滿足存在和不存在兩種情況

先看使用exists如何查詢不為null

post /kaka/_search
{
  "query":{
    "constant_score":{
      "filter":{
        "exists":{
          "field":"tags"
        }
      }
    }
  }
}

再看使用exists查詢為null的

post /kaka/_search
{
  "query":{
    "bool":{
      "must_not":{
        "exists":{
          "field":"tags"
        }
      }
    }
  }
}

三、使用null_value替換顯示的空值

刪除上邊定義的索引delete kaka,然後自定義mapping,給tags設置"null_value" : "null",用指定的值替換顯示的空值,”null”可以自定義為任意值

使用了null_value這樣做的好處就是空字段也可以被索引,同時也不會在查詢時報field name is null or empty的錯誤

put kaka
{
  "mappings":{
    "properties":{
      "tags" :{
        "type":"keyword",
        "null_value":"null"
      }
    }
  }
}

再插入上邊的數據

POST /kaka/_bulk
"index": { "_id""1"}}
"tags" : ["search"]}  
"index": { "_id""2"}}
"tags" : ["search""open_source"] }  
"index": { "_id""3"}}
"tags" : null                      }  
"index": { "_id""4"}}
"tags" :"null"}

再次執行查詢為null的數據,就會出現第3、4條數據

post /kaka/_search
{
  "query":{
    "term": {
      "tags""null"
    }
  },
  "profile":"true"
}

四、使用null_value注意點

null_value必須和定義的數據類型匹配,例如long類型的不能定義字符串類型的value_null值

看一下long類型設置了字符串類型value_null會出現什麼錯誤

# 錯誤演示,long類型使用了字符串類型的null_value值
put kaka
{
  "mappings":{
    "properties":{
      "tags" :{
        "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
}

注意了數據類型外,你還需要知道value_null不是任何類型都可以使用的,以下列舉的類型都可使用null_value

  • Array
  • Boolean
  • Date
  • geo_point
  • ip
  • keyword
  • Numeric
  • point

堅持學習、堅持寫作、堅持分享是咔咔從業以來所秉持的信念。願文章在偌大的互聯網上能給你帶來一點幫助,我是咔咔,下期見。