關於動態Mappin-多字段映射

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/

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