前言
一般的,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"
}
}
}
}
}
現在再來測試一下false
和true
有什么區別:
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
一下此時m2
的mappings
信息:
{
"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