ES索引中的字段映射_7_1

映射(mapping)是定義文檔及其包含字段的存儲和索引方式的一組過程
字段映射需要考慮的問題:
1)、哪個string類型的字段應該作爲全文索引;
2)、哪些字段應該包含數字,日期或者地理位置;
3)、日期類型值應該被如何格式化;
4)、自定義規則來控制動態添加字段的映射;

映射的定義包含以下兩個部分:

1、ES索引結構元字段

標識元字段:表示文檔相關元數據

序號 類型 說明
1 _index 表示文檔所屬索引名稱
2 _type 表示文檔所屬索引的類型名稱,7.x之後均爲_doc
3 _id 文檔唯一id

文檔數據元字段

序號 類型 說明
1 _source 文檔原始JSON數據
2 _size _source字段內容的字節大小(需安裝mapper-size插件)

索引元字段

序號 類型 說明
1 _field_names 記錄索引文檔的所有non_null值的字段
2 _ignored 文檔中所有在索引時指定無需索引字段(使用ignore_malformed標識)

路由元字段

序號 類型 說明
1 _routing 自定義路由值,將文檔路由到指定分片

其它元字段

序號 類型 說明
1 _meta 由應用指定的元數據,可看做應用的標識數據

2、文檔內容屬性

字段類型
1)、簡單類型有text,keyword,date,long,double,boolean或ip;
2)、支持json分層的類型,如object或者nested;
3)、專門類型,如geo_point,geo_shape或completion;

實際場景中我們可能希望在不同場景以不同的方式使用相同的字段,這可以使用多字段(multi-fields)映射處理,例如一個string類型字段可以被映射成text字段以用於全文檢索,同時也可以作爲提個keyword類型用於排序或者聚合操作,甚至可以將同一個字段使用不同的分詞器(standard analyzer、english analyzer、french analyzer)進行分詞處理;

防止字段映射衝突的設置
同一個索引當中映射太多的字段可能會導致映射衝突,進而會導致內存不足以及數據無法恢復的情況;
在開啓動態映射的情況下,若新插入的文檔中有未被映射的字段,在插入之時新的字段將會添加到索引映射當中,這樣隨着映射的增加可能會導致問題;
以下設置可以限制索引映射字段的數量以防止產生映射衝突情況:

序號 類型 說明
1 index.mapping.total_fields.limit 索引映射字段最大值,字段和對象的映射以及字段別名都計入此限制,默認值1000
2 index.mapping.depth.limit 索引字段的最大深度,以內部對象的數量衡量;若所有字段都在跟對象級別定義,則深度爲1,若有一個對象映射,則深度爲2,以此類推,默認值20;
3 index.mapping.nested_fields.limit 索引中不同嵌套(nested)映射最大值,嵌套(nested)類型應該只用於特殊場景(對象數組的查詢記錄是相互獨立的情況),爲防止不良的映射,默認值50;
4 index.mapping.nested_objects.limit 索引中單個文檔可包含嵌套(nested)JSON對象的最大值,此參數可限制文檔包含太多嵌套對象(可能會導致內存不足),默認值10000;
5 index.mapping.field_name_length.limit 索引值字段名長度最大值,該設置並不能解決映射衝突的問題,但對於限制字段名長度來說是可用的;通常不需要配置此參數,除非添加的記錄字段名稱長度非常長,默認值Long.MAX_VALUE;

動態映射
字段類型和映射類型不需要在使用前定義,通過動態映射,新的字段名通過索引會被自動映射,新的字段既可以映射爲頂級類型,同時也可以映射爲內部對象或嵌套類型;

顯式映射
相較於ES的自動映射,處理數據的我們對於數據的熟悉程度肯定要比ES更多,故在一些特殊的場景下顯式設置字段映射效果會更好;
1)、創建索引時指定字段類型

PUT /explicit_definition_index
{
  "mappings": {
    "properties": {
      "age":{
        "type": "integer"
      },
      "email":{
        "type": "keyword"
      },
      "name":{
        "type": "text"
      }
    }
  }
}

2)、向索引中添加新字段
除了es支持修改的映射參數外,es不允許更改現有字段映射或字段類型,更改現有字段可能會使已經建立索引的數據無效;
若想更改映射中的字段,最好是創建一個新的索引並將原索引中數據導入到新的索引中;
重命名字段會使舊字段名稱下已建立索引的數據無效,可以創建一個新的字段並將其類型置爲alias;

//查看索引映射詳情
GET /explicit_definition_index/_mapping

{
  "explicit_definition_index" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "email" : {
          "type" : "keyword"
        },
        "name" : {
          "type" : "text"
        }
      }
    }
  }
}

//查看映射字段詳情
GET /explicit_definition_index/_mapping/field/age

{
  "explicit_definition_index" : {
    "mappings" : {
      "age" : {
        "full_name" : "age",
        "mapping" : {
          "age" : {
            "type" : "integer"
          }
        }
      }
    }
  }
}

移除索引的類型的原因
將ES對比DB是不恰當的比喻,在數據庫當中,表與表之間是相互物理獨立的,繼而字段與字段之間也是相互獨立的,但是在ES中並非如此,ES底層是基於Lucene做字段的存儲,若不同的索引擁有相同的字段名稱而其字段類型不同,在存儲上都使用的是同一個字段名稱,這可能會導致數據上的一些問題,最重要的是存儲在同一索引中幾乎沒有或完全沒有相同字段的數據會導致數據稀疏分佈並干擾Lucene有效壓縮文檔的能力,基於以上原因決定需要移除索引的類型概念;

自定義type字段,可顯式在索引中指定type字段以用於類型區分(如果有需要的話)

//索引數據遷移
// 新建索引
PUT /new_index
{
  "settings": {
    "index.mapping.single_type":true
  },
  "mappings": {
    "_doc":{
      "properties":{
        
      }
    }
  }
}
// 索引數據遷移
POST _reindex
{
  "source": {
    "index": "",
    "type": ""
  },
  "dest": {
    "index": "new_index",
    "type":"_doc"
  }
}
// 自定義索引類型
POST _reindex
{
  "source": {
    "index": ""
  },
  "dest": {
    "index": "new_index"
  },
  "script": {
    "source": """
      ctx._source.type = ctx._type;
      ctx._id = ctx._type + '-' + ctx._id;
      ctx._type = '_doc'
    """
  }
}

參考文檔
壓縮技術:http://www.360doc.com/content/19/0722/00/40661497_850235499.shtml

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