elasticsearch mappings之dynamic的三種狀態


前言

一般的,mapping則又可以分為動態映射(dynamic mapping)和靜態(顯式)映射(explicit mapping)和精確(嚴格)映射(strict mappings),具體由dynamic屬性控制。

動態映射(dynamic:true)

現在有這樣的一個索引:

PUT m1
{
  "mappings": {
    "doc":{
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

通過GET m1/_mapping看一下mappings信息:

{
  "m1" : {
    "mappings" : {
      "doc" : {
        "dynamic" : "true",
        "properties" : {
          "age" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text"
          }
        }
      }
    }
  }
}

添加一些數據,並且新增一個sex字段:

PUT m1/doc/1
{
  "name": "小黑",
  "age": 18,
  "sex": "不詳"
}

當然,新的字段查詢也沒問題:

GET m1/doc/_search
{
  "query": {
    "match": {
      "sex": "不詳"
    }
  }
}

返回結果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "m1",
        "_type" : "doc",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "小黑",
          "age" : 18,
          "sex" : "不詳"
        }
      }
    ]
  }
}

現在,一切都很正常,跟elasticsearch自動創建時一樣。那是因為,當 Elasticsearch 遇到文檔中以前未遇到的字段,它用動態映射來確定字段的數據類型並自動把新的字段添加到類型映射。我們再來看mappings你就明白了:

{
  "m1" : {
    "mappings" : {
      "doc" : {
        "dynamic" : "true",
        "properties" : {
          "age" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text"
          },
          "sex" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}

通過上例可以發下,elasticsearch幫我們新增了一個sex的映射。所以。這一切看起來如此自然。這一切的功勞都要歸功於dynamic屬性。我們知道在關系型數據庫中,字段創建后除非手動修改,則永遠不會更改。但是,elasticsearch默認是允許添加新的字段的,也就是dynamic:true
其實創建索引的時候,是這樣的:

PUT m1
{
  "mappings": {
    "doc":{
      "dynamic":true,
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

上例中,當dynamic設置為true的時候,elasticsearch就會幫我們動態的添加映射屬性。也就是等於啥都沒做!
這里有一點需要注意的是:mappings一旦創建,則無法修改。因為Lucene生成倒排索引后就不能改了。

靜態映射(dynamic:false)

現在,我們將dynamic值設置為false

PUT m2
{
  "mappings": {
    "doc":{
      "dynamic":false,
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

現在再來測試一下falsetrue有什么區別:

PUT m2/doc/1
{
  "name": "小黑",
  "age":18
}
PUT m2/doc/2
{
  "name": "小白",
  "age": 16,
  "sex": "不詳"
}

第二條數據相對於第一條數據來說,多了一個sex屬性,我們以sex為條件來查詢一下:

GET m2/doc/_search
{
  "query": {
    "match": {
      "sex": "不詳"
    }
  }
}

結果如下:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

結果是空的,也就是什么都沒查詢到,那是為什呢?來GET m2/_mapping一下此時m2mappings信息:

{
  "m2" : {
    "mappings" : {
      "doc" : {
        "dynamic" : "false",
        "properties" : {
          "age" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text"
          }
        }
      }
    }
  }
}
```
可以看到elasticsearch並沒有為新增的`sex`建立映射關系。所以查詢不到。
當elasticsearch察覺到有新增字段時,因為`dynamic:false`的關系,會忽略該字段,但是仍會存儲該字段。
在有些情況下,`dynamic:false`依然不夠,所以還需要更嚴謹的策略來進一步做限制。

# 嚴格模式(dynamic:strict)

讓我們再創建一個`mappings`,並且將`dynamic`的狀態改為`strict`:

```
PUT m3
{
  "mappings": {
    "doc": {
      "dynamic": "strict", 
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}
```
現在,添加兩篇文檔:
```
PUT m3/doc/1
{
  "name": "小黑",
  "age": 18
}
PUT m3/doc/2
{
  "name": "小白",
  "age": 18,
  "sex": "不詳"
}
```
第一篇文檔添加和查詢都沒問題。但是,當添加第二篇文檔的時候,你會發現報錯了:
```
{
  "error": {
    "root_cause": [
      {
        "type": "strict_dynamic_mapping_exception",
        "reason": "mapping set to strict, dynamic introduction of [sex] within [doc] is not allowed"
      }
    ],
    "type": "strict_dynamic_mapping_exception",
    "reason": "mapping set to strict, dynamic introduction of [sex] within [doc] is not allowed"
  },
  "status": 400
}
```
錯誤提示,嚴格動態映射異常!說人話就是,當`dynamic:strict`的時候,elasticsearch如果遇到新字段,會拋出異常。
上述這種嚴謹的作風灑家稱為——嚴格模式!

小結:

- 動態映射(dynamic:true):動態添加新的字段(或缺省)。
- 靜態映射(dynamic:false):忽略新的字段。在原有的映射基礎上,當有新的字段時,不會主動的添加新的映射關系,只作為查詢結果出現在查詢中。
- 嚴格模式(dynamic: strict):如果遇到新的字段,就拋出異常。

一般靜態映射用的較多。就像`HTML`的`img`標簽一樣,`src`為自帶的屬性,你可以在需要的時候添加`id`或者`class`屬性。
當然,如果你非常非常了解你的數據,並且未來很長一段時間不會改變,`strict`不失為一個好選擇。
<hr>
see also: [Elasticsearch - 索引](https://www.jianshu.com/p/ee6413896a2b)
歡迎斧正,that's all


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM