[Elasticsearch] 索引管理 (四) - 動態映射

動態映射(Dynamic Mapping)

當ES在文檔中碰到一個之前沒見過的字段時,它會利用動態映射來決定該字段的類型,並自動地對該字段添加映射。html

有時這正是須要的行爲,但有時不是。你或許不知道在之後你的文檔中會添加哪些字段,可是你想要它們可以被自動地索引。或許你只是想要忽略它們。或者 - 尤爲當你將ES當作主要的數據存儲使用時 - 大概你會但願這些未知的字段會拋出異常來提醒你注意這一問題。json

幸運的是,你能夠經過dynamic設置來控制這一行爲,它可以接受如下的選項:app

  • true:默認值。動態添加字段
  • false:忽略新字段
  • strict:若是碰到陌生字段,拋出異常

dynamic設置能夠適用在根對象上或者object類型的任意字段上。你應該默認地將dynamic設置爲strict,可是爲某個特定的內部對象啓用它:elasticsearch

PUT /my_index
{
    "mappings": {
        "my_type": {
            "dynamic":      "strict", 
            "properties": {
                "title":  { "type": "string"},
                "stash":  {
                    "type":     "object",
                    "dynamic":  true 
                }
            }
        }
    }
}

my_type對象上若是碰到了未知字段則會拋出一個異常。 在stash對象上會動態添加新字段。ide

經過以上的映射,你能夠向stash添加新的可搜索的字段:ui

PUT /my_index/my_type/1
{
  "title": "This doc adds a new field",
  "stash": {
    "new_field": "Success!"
  }
}

可是,若是在頂層對象上試圖添加新字段則會失敗:spa

PUT /my_index/my_type/1
{
    "title":     "This throws a StrictDynamicMappingException",
    "new_field": "Fail!"
}

NOTEcode

dynamic設置爲false並不會改變_source字段的內容 - _source字段仍然會保存你索引的整個JSON文檔。只不過是陌生的字段將不會被添加到映射中,以致於它不能被搜索到。orm

自定義動態映射

若是你知道你須要動態的添加的新字段,那麼你也許會啓用動態映射。然而有時動態映射的規則又有些不夠靈活。幸運的是,你能夠調整某些設置來讓動態映射的規則更加適合你的數據。htm

date_detection

當ES碰到一個新的字符串字段時,它會檢查該字串是否含有一個可被識別的日期,好比2014-01-01。若是存在,那麼它會被識別爲一個date類型的字段。不然會將它做爲string進行添加。

有時這種行爲會致使一些問題。若是你想要索引一份這樣的文檔:

{ "note": "2014-01-01" }

假設這是note字段第一次被發現,那麼根據規則它會被做爲date字段添加。可是若是下一份文檔是這樣的:

{ "note": "Logged out" }

這時該字段顯然不是日期,可是已經太遲了。該字段的類型已是日期類型的字段了,所以這會致使一個異常被拋出。

能夠經過在根對象上將date_detection設置爲false來關閉日期檢測:

PUT /my_index
{
    "mappings": {
        "my_type": {
            "date_detection": false
        }
    }
}

有了以上的映射,一個字符串老是會被當作string類型。若是你須要一個date字段,你須要手動地添加它

NOTE

ES中識別日期的方法能夠經過dynamic_date_formats設置改變。

dynamic_templates

經過dynamic_templates,你能夠擁有對新字段的動態映射規則擁有徹底的控制。你設置能夠根據字段名稱或者類型來使用一個不一樣的映射規則。
每一個模板都有一個名字,能夠用來描述這個模板作了什麼。同時它有一個mapping用來指定具體的映射信息,和至少一個參數(好比match)用來規定對於什麼字段須要使用該模板。
模板的匹配是有順序的 - 第一個匹配的模板會被使用。好比咱們能夠爲text字段指定兩個模板:

  • es:以_es結尾的字段應該使用spanish解析器
  • en:其它全部字段使用english解析器

咱們須要將es模板放在第一個,由於它相比可以匹配全部字符串字段的en模板更加具體:

PUT /my_index
{
    "mappings": {
        "my_type": {
            "dynamic_templates": [
                { "es": {
                      "match":              "*_es", 
                      "match_mapping_type": "text",
                      "mapping": {
                          "type":           "text",
                          "analyzer":       "spanish"
                      }
                }},
                { "en": {
                      "match":              "*", 
                      "match_mapping_type": "text",
                      "mapping": {
                          "type":           "text",
                          "analyzer":       "english"
                      }
                }}
            ]
}}}

match_mapping_type容許你只對特定類型的字段使用模板,正如標準動態映射規則那樣,好比text,long等。
match參數只會匹配字段名,path_match參數用於匹配對象中字段的完整路徑,好比address.*.name能夠匹配以下字段:

{
    "address":
        "city":
            "name": "New York"
        }
    }
}

unmatchpath_unmatch模式可以用來排除某些字段,沒有被排除的字段則會被匹配。

更多的配置選項能夠在根對象的參考文檔中找到。

相關文章
相關標籤/搜索