1. 類型判定
ElasticSearch在創建index的時候是可以不指定schema的,那麼它是怎麼知道你使用的是什麼類型呢?實際上它是通過給定 document的json來判定的,例如,string的話是用引號引起來的,數字是光溜溜的,boolean類型是true或者false等等。這個 規則非常的簡單,但是非常有效。例如有如下的json:
{ "field1": "hello", "field2": 1024 }
ES能夠很容易判定field1爲string類型,field2爲數字類型,但是有些情況下,需要把所有的格式都存爲string,true和 false就不行了,因爲ES會優先將其存爲boolean類型,這就需要我們手動指定schema,另外一個問題是,如果我們對某個index首次插入 數據的時候爲某個field插入了一個數字類型,例如:
curl -XPUT localhost:9200/blog/article/1?pretty -d '{ "field1" : 1024}'
我們可以查看其mapping:
curl -XGET localhost:9200/blog/_mapping?pretty
我們可以看到其schem如下:
{ "blog" : {
"article" : {
"properties" : {
"field1" : {
"type" : "long",
"ignore_malformed" : false
}
}
}
}
}
這說明ES已經將該字段的類型定義爲long了,然後如果我們插入string,那麼就會報錯,說類型不匹配:
curl -XPUT localhost:9200/blog/article/2?pretty -d '{
"field1" : "test string"
}'
返回結果爲:
{ "error" : "MapperParsingException[Failed to parse [field1]];
nested: NumberFormatException[For input string:
\"test string\"]; ", "status" : 400 }
但是,如果繼續插入float型數據是可以的,因爲long可以轉換爲float,如下:
curl -XPUT localhost:9200/blog/article/2?pretty -d '{
"field1" : 3.14
}'
這時,我們在查看schema,可以看到ES將schema修改了。這就會對我們的數據精度造成影響,爲了防止這種情況,或者爲了防止已經存在的index添加字段,我們可以將動態schema關閉,如下:
{ "blog" : { "article" : { "dynamic" : "false", "properties" : { ... } } } }
2.動態mapping
有時,我們需要通過json中的field和type來決定我們使用的mapping,這時,動態templates就派上用場了。動態 templates和普通的mapping類似,它有一個自己的模式,如果一個field的名字匹配了該模式,該template就會使用,下面是定義模 式的兩種手段:
match: template在field名匹配的時候起用。
unmatch: template在field名不匹配的時候起用。
當然,也可以使用path_match和path_unmatch對嵌套field使用。
定義field的使用可以使用
{name}: document最初寫入數據的field的名字。
{dynamic_type}: document最初寫入數據的field的type。
需要提醒的是,ES是按照你寫的templates的順序來匹配的,因此,匹配範圍越廣的應該放在越後,不然就會將所有後面的正則攔掉了。例如*應該放在最後:
{ "mappings" : { "article" : { "dynamic_templates" : [ { "template_test": { "match" : "*", "mapping" : { "type" : "multi_field", "fields" : { "{name}": { "type" : "{dynamic_type}"}, "str": {"type" : "string"} } } } }] } } }
例如我在logstash的日誌發現了一個錯誤,如下
"response"=>"-"
"error"=>"MapperParsingException[failed to parse [response];
nested: NumberFormatException[For input string: \"-\"; "
,這是因爲我之前在mapping中定義了response爲long類型,現在寫入的數據中出現了response=> "-",導致報錯類型不匹配。
{
"dynamic_templates" : [ {
"response_fields": {
"match" : "*",
"mapping" : {
"type" : "multi_field",
"fields" : {
"response": { "type" : "long"}, "str": {"type" : "string"}
}
}
}
}
}
文章原鏈:http://www.dengchuanhua.com/