1. 程式人生 > >ES mapping 詳解

ES mapping 詳解

1 mapping type

對映(mapping)

對映是定義一個文件以及其所包含的欄位如何被儲存和索引的方法。

例如,用對映來定義以下內容:

  • 哪些 string 型別的 field 應當被當成當成 full-text 欄位
  • 哪些欄位應該是數值型別、日期型別或者是地理位置資訊
  • 日期型別欄位的格式是怎麼樣的
  • 是否文件的所有欄位都需要被索引到 _all 欄位
  • 動態增加的 field 可以由使用者自定義的模板來控制其行為

對映型別(mapping types)

每個索引都有一個或多個對映型別(mapping type)來對索引內的文件進行邏輯分組(mapping type 就是平常所說的 type)。

每一個對映型別都包含以下內容:

1. 元資料欄位

元資料欄位用來自定義如何處理關聯文件的元資料。元資料欄位包括: _index, _type, _id, _source.

2. 欄位列表或屬性

每個對映型別都包含一個欄位列表或者是和該型別相關的一些屬性。

欄位資料型別(field datatypes)

每一個欄位,都屬於一種資料型別。

1. 基本資料型別

string, long, boolean, ip

2. JSON 分層資料型別

object, nested

3. 特殊型別

geo_point, geo_shape, completion

動態對映(dynamic mapping)

欄位及其對映型別不必在使用前事先定義好,這得益於動態對映的應用。

動態對映能夠根據文件索引過程來自動生成對映型別和欄位名。

動態對映規則可以用來定義新型別和新欄位的對映。

顯式對映(explicit mappings)

如果你比 ES 通過猜測來確定對映更加了解你的資料,那麼定義一個動態對映將會很有用。不過有時候你可能需要指定自己的顯式對映。

顯式對映可以在建立索引時候定義,或者用 mapping API 來為已有的索引新增對映型別或欄位。

對映更新(updating existing mappings)

對映支援更新,如果需要,必須重建索引並設定正確的 mapping ,而不是試圖去更新已有的 mapping。

欄位之間共享對映型別(fileds are shared across mapping types)

對映型別用來邏輯分組欄位,但是每個對映型別之間的欄位並非獨立存在的。

1. 規則:

欄位在以下條件:

  1. 相同欄位名
  2. 相同索引
  3. 不同對映型別

的時候其實是對映到內部相同的欄位上,所以,必須擁有相同的對映設定。

2. 例外:

有一些例外,引數:

  1. copy_to
  2. dynamic
  3. enabled
  4. ignore_above
  5. include_in_all
  6. properties

可以對滿足前述“規則”的欄位進行各自不同的設定。

 2 field datatypes

基本型別

1. 字串

字串型別被分為兩種情況:full-text 和 keywords。

full-text 表示欄位內容會被分析,而 keywords 表示欄位值只能作為一個精確值查詢。

引數:

analyzerboostdoc_valuesfielddatafieldsignore_aboveinclude_in_allindexindex_optionsnormsnull_valueposition_increment_gapstoresearch_analyzersearch_quote_analyzersimilarityterm_vector

 

2. 數值

數值型別包括: long, integer, short, byte, double, float 。

引數:

coerceboostdoc_valuesignore_malformedinclude_in_allindexnull_valueprecision_stepstore

 

3. 日期

JSON 本身並沒有日期資料型別,在 ES 中的日期型別可以是:

  • 類似 "2015-01-01" or "2015/01/01 12:10:30" 的字串
  • long 型別的毫秒級別的時間戳
  • int 型別的秒級別的時間戳

日期型別預設會被轉換為 UTC 並且轉換為毫秒級別的時間戳的 long 型別儲存。

日期型別如果不指定 format ,將會以預設格式表示。

引數:

boostdoc_valuesformatignore_malformedinclude_in_allindexnull_valueprecision_stepstore

 

4. 布林

布林假:    false"false""off""no""0""" (empty string), 00.0 。

布林真:    任何不為假的值。

像 terms aggregation 聚合,是使用 1 和 0 來作為 key 的,key_as_string 則是用字串 true 和 false

布林型別的值,在 scripts 中則始終返回 1 或 0

引數:

boostdoc_valuesindexnull_valuestore

 

5. 二進位制

二進位制型別以 Base64 編碼方式接收一個二進位制值,二進位制型別欄位預設不儲存,也不可搜尋。

引數:doc_valuesstore

 

複雜型別

1. 物件

JSON 格式本身是分層級的——文件可以包含物件,物件還可以包含子物件。不過,在 ES 內部 "物件" 被索引為一個扁平的鍵值對。

例如:


PUT my_index/my_type/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": { 
      "first": "John",
      "last":  "Smith"
    }
  }
}

轉換為:


{
  "region":             "US",
  "manager.age":        30,
  "manager.name.first": "John",
  "manager.name.last":  "Smith"  //層級結構被以 "." 來表示。
}

 

2. 陣列

陣列型別,要求陣列元素的資料型別必須一致。

  • 字串陣列: [ "one""two" ]
  • 數字陣列: [ 12 ]
  • 陣列陣列: [ 1, [ 23 ]] which is the equivalent of [ 123 ]
  • 物件陣列: [ { "name": "Mary", "age": 12 }{ "name": "John", "age": 10 }

陣列元素的資料型別,將會由其第一個元素的資料型別決定。

物件陣列,在 ES 內部將會被轉換為 "多值" 的扁平資料型別。後面將會詳解這一點。

例如:


PUT my_index/my_type/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

轉轉為:

{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

 

3. 物件陣列

物件陣列在 ES 內部,會把所有陣列元素(即物件)合併,物件中的每一個欄位被索引為一個 "多值" 欄位。

這將導致每個陣列元素(物件)內部的欄位關聯性丟失,解決的方法是使用 nested 型別

例如:


PUT my_index/my_type/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": [
    { 
      "first": "John",
      "last":  "Smith"
    },
    { 
      "first": "Bob",
      "last":  "Leo"
    }
    ]
  }
}

轉換為:


{
  "region":             "US",
  "manager.age":        30,
  "manager.name.first": "John Bob",
  "manager.name.last": "Smith Leo" 
}
// 如果我們搜尋:
"bool": {
      "must": [
        { "match": { "manager.name.first": "John" }},   // John Smith
        { "match": { "manager.name.last": "Leo"}}       // Bob Leo
      ]
}
//這將會導致導致文件被命中,顯然,John Smith 、Bob Leo 兩組欄位它們內在的關聯性都丟失了

引數:

dynamicenabledinclude_in_allproperties

 

4. 巢狀(nested)

巢狀型別是一個特殊物件型別,巢狀型別允許對物件陣列的每一個元素(物件)相互獨立的進行查詢,也即他們不會被合併為一個物件。

巢狀型別的文件可以:

例如:


PUT my_index/my_type/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": [
    { 
      "first": "John",
      "last":  "Smith"
    },
    { 
      "first": "Bob",
      "last":  "Leo"
    }
    ]
  }
}

轉換為:


{
  "region":             "US",
  "manager.age":        30,
  {
      "manager.name.first": "John",
      "manager.name.last": "Smith"
  },
  {
      "manager.name.first": "Bob",
      "manager.name.last": "Leo" 
  }
}
// 如果我們搜尋:
"bool": {
      "must": [
        { "match": { "manager.name.first": "John" }},   // John Smith
        { "match": { "manager.name.last": "Leo"}}       // Bob Leo
      ]
}
//這樣的查詢將不能命中文件!!!

引數:

dynamicinclude_in_allproperties

 

專有型別

1. IPV4型別

IPV4 資料型別其實質是個 long 型別,不過其能接收一個 IPV4 地址並且將他轉換為 long 型別存放。

引數:

boostdoc_valuesinclude_in_allindexnull_valueprecision_stepstore

 

3 Meta-Fields

文件標識相關元資料欄位

_index

  • 當執行多索引查詢時,可能需要新增特定的一些與文件有關聯的索引的子句。
  • _index 欄位可以用在 term、terms 查詢,聚合(aggregations)操作,指令碼(script)操作以及用來排序(sort)。


GET index_1,index_2/_search
{
  "query": {
    "terms": {
      "_index": ["index_1", "index_2"] 
    }
  },
  "aggs": {
    "indices": {
      "terms": {
        "field": "_index", 
        "size": 10
      }
    }
  },
  "sort": [
    {
      "_index": { 
        "order": "asc"
      }
    }
  ],
  "script_fields": {
    "index_name": {
      "script": "doc['_index']" 
    }
  }
}

_type

  • _type 可以用來讓針對具體 type 的搜尋更加快。
  • _type 欄位可以用在 querys、aggregations、scripts 以及 sorting。


GET my_index/_search/type_*
{
  "query": {
    "terms": {
      "_type": [ "type_1", "type_2" ] 
    }
  },
  "aggs": {
    "types": {
      "terms": {
        "field": "_type", 
        "size": 10
      }
    }
  },
  "sort": [
    {
      "_type": { 
        "order": "desc"
      }
    }
  ],
  "script_fields": {
    "type": {
      "script": "doc['_type']" 
    }
  }
}


原始資訊相關元資料欄位

_source

欄位說明

  • _source 欄位存放的是文件的原始 JSON 資訊
  • _source 欄位不被 indexed ,不過被 stored ,所以可以通過 get 或 search 取得該欄位的值。

禁用_source欄位

  • _source 欄位可以在 mapping 設定中禁用
  • 如果禁用 _source 欄位將會有一些其它影響,比如:update API 將無法使用等等。


PUT tweets
{
  "mappings": {
    "tweet": {
      "_source": {
        "enabled": false
      }
    }
  }
}

_source排除特定欄位

  • 在 _source 的 mapping 設定中可以通過 includes 和 excludes 引數來包含或排除特定欄位
  • 包含或排除的欄位,需要以 plain 格式的 field 名稱,名稱支援萬用字元。


PUT logs
{
  "mappings": {
    "event": {
      "_source": {
        "includes": [
          "*.count",
          "meta.*"
        ],
        "excludes": [
          "meta.description",
          "meta.other.*"
        ]
      }
    }
  }
}

 

索引操作相關元資料欄位

_all

欄位說明

  • _all 欄位把其他所有欄位的內容儲存到一個大的字串中,不管其它欄位是什麼資料型別,在 _all 中都被當作字串處理。
  • 每個 index 只有一個 _all 欄位。
  • 該字串會被 analyzed 和 indexed,但不會 store(儲存)。可以被搜尋,但無法用來恢復。
  • _all 欄位也和普通字串欄位一樣可以接收:analyzer、term_vectors、index_options 和 store 等引數。
  • 生成 _all 欄位是有資源消耗的,會消耗 CPU 和 disk 儲存。


GET my_index/_search
{
  "query": {
    "match": {
      "_all": "john smith 1970"
    }
  }
}

_all欄位查詢

  • query_string 和 simple_query_string 查詢操作,預設就是查詢 _all 欄位,除非自己明確指定。


GET _search
{
  "query": {
    "query_string": {
      "query": "john smith 1970"
    }
  }
}

禁用_all欄位

  • _all 欄位可以在 mapping 設定中完全禁用,如果禁用,query_string 和 simple_query_string 查詢操作需要指定預設欄位才可用。


PUT my_index
{
  "mappings": {
    "my_type": {
      "_all": {
        "enabled": false 
      },
      "properties": {
        "content": {
          "type": "string"
        }
      }
    }
  },
  "settings": {
    "index.query.default_field": "content" 
  },
}

_all排除特定欄位

  • 欄位通過 mapping 設定可以通過 include_in_all 引數控制該欄位否包含在 _all 欄位。


PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "date": { 
          "type": "date",
          "include_in_all": false
        }
      }
    }
  }
}

_all欄位儲存

  • _all 欄位可以通過引數 store 來設定其是否儲存。


PUT myindex
{
  "mappings": {
    "mytype": {
      "_all": {
        "store": true
      }
    }
  }
}

_field_names

欄位說明

  • _field_names 欄位是用來儲存文件中所有非 null 欄位的欄位名稱的。
  • 該欄位供 exists 和 missing 查詢使用,來查詢某個文件中是否包含或不包含某個欄位。


GET my_index/_search
{
  "query": {
    "terms": {
      "_field_names": [ "title" ] 
    }
  },
  "aggs": {
    "Field names": {
      "terms": {
        "field": "_field_names", 
        "size": 10
      }
    }
  },
  "script_fields": {
    "Field names": {
      "script": "doc['_field_names']" 
    }
  }
}


路由相關元資料欄位

_parent

欄位說明

  • 在同一個 index 中,可以通過設定 type 的父子關係來建立文件之間的父子關係。
  • 父子 type 必須是不同的 type。
  • 指定的 parent type 必須要是還不存在的,已存在的 type 不能作為其它 type 的 parent type。
  • 父子關係的 doc 必須被索引到相同的 shard 上,子文件通過引數 parent 引數來作為其 routing 來保證索引到相同分片。 


PUT my_index
{
  "mappings": {
    "my_parent": {},
    "my_child": {
      "_parent": {
        "type": "my_parent" 
      }
    }
  }
}

_routing

  • _routing 欄位用來確定文件索引的分片:shared_num = hash(routing) % num_primary_shards
  • 預設的 _routing 是文件的 _id 或 _parent 的 ID。
  • 通過 routing 引數可以自定義 _routing 的值。


GET my_index/_search
{
  "query": {
    "terms": {
      "_routing": [ "user1" ] 
    }
  },
  "aggs": {
    "Routing values": {
      "terms": {
        "field": "_routing", 
        "size": 10
      }
    }
  },
  "sort": [
    {
      "_routing": { 
        "order": "desc"
      }
    }
  ],
  "script_fields": {
    "Routing value": {
      "script": "doc['_routing']" 
    }
  }
}

4 mapping setting

mapping type

對映設定一般發生在:

1. 增加新的 index 的時候,新增 mapping type,對 fields 的對映進行設定


PUT twitter 
{
  "mappings": {
    "tweet": {
      "properties": {
        "message": {
          "type": "string"
        }
      }
    }
  }
}

 

2. 為 index 增加新的 mapping type,對 fields 的對映進行設定


PUT twitter/_mapping/user 
{
  "properties": {
    "name": {
      "type": "string"
    }
  }
}

 

3. 為已有 mapping type 增加新的 fields 對映設定


PUT twitter/_mapping/tweet 
{
  "properties": {
    "user_name": {
      "type": "string"
    }
  }
}

 

設定方式

1. 在 PUT 請求體中給出完整的 mapping 設定


PUT twitter 
{
  "mappings": {                         //mappings 物件,說明進行 mapping 設定
    "tweet": {                          //指定 mapping type
      "properties": {                   //指定 mapping type 的 properties 設定
        "message": {                    //對欄位 message 的對映進行設定
          "type": "string"              //mapping 引數配置
        }
      }
    }
  }
}


增加 index 的時候,除了可以設定 mapping type,還可以對 index 進行設定,比如配置自定義 analyzer、索引分片個數設定等


PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "autocomplete": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "autocomplete_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "my_type": {
      "properties": {
        "text": {
          "type": "string",
          "analyzer": "autocomplete"
        }
      }
    }
  }
}

 

2. 在 PUT 請求 URI 中指定 type,並在請求體中給出 type 的各項設定


PUT twitter/_mapping/user 
{
  "properties": {                   //指定 mapping type 的 properties 設定
    "name": {                       //對欄位 message 的對映進行設定
      "type": "string"              //mapping 引數配置
    }
  }
}


3. 一個完整的 mapping type 設定包括:Meta-fields 和 Fields 或者 properties 設定


PUT my_index
{
  "mappings": {
    "type_1": { 
      "properties": {...}           //properties 設定
    },
    "type_2": { 
      "_all": {                     //meta-fields 設定
        "enabled": false
      },
      "properties": {...}
    }
  }
}


5 dynamic mapping

概述

在使用 ES 的時,我們不需要事先定義好對映設定就可以直接向索引中匯入文件。ES 可以自動實現每個欄位的型別檢測,並進行 mapping 設定,這個過程就叫動態對映(dynamic mapping)。

動態對映可以通過以下設定來關閉。

PUT /_settings 
{
  "index.mapper.dynamic":false
}

動態對映的規則也可以自定義,有以下幾種我們可以自定義規則的應用場景:

  1. 預設對映(_default_ mapping)
  2. 欄位動態對映(dynamic field mapping)
  3. 動態模板(dynamic template)
  4. 索引模板(index template)

其中,前 3 個條件中都是針對特定 index 下的 type 進行設定,而條件 4 是針對所有滿足條件的 index 進行設定。

 

預設對映

預設對映通過把 mapping type 設定為 _default_ 來定義。

預設對映將會應用到該 index 下的任意新增 type 中。

預設對映可以在新增 index 時候設定,也可以建立 index 之後再通過 PUT mapping 介面進行設定。


PUT my_index
{
  "mappings": {
    "_default_": { 
      "_all": {
        "enabled": false         //預設對映禁用掉所有新增 type 的 _all 元資料欄位
      }
    },
    "user": {}, 
    "blogpost": { 
      "_all": {
        "enabled": true     //覆蓋 _default_ 的設定,啟用 _all 欄位
      }
    }
  }
}

 

欄位動態對映

預設情況,發現新的欄位,ES 自動檢測其 datatype 並將其加入到 mapping type 中。

通過一些設定,我們可以控制欄位動態對映的方式,包括:日期型別檢測、數值型別檢測、自定義日期型別的格式等。


PUT my_index         //禁用日期型別檢測
{
  "mappings": {
    "my_type": {
      "date_detection": false
    }
  }
}
PUT my_index       //自定義日期型別的格式
{
  "mappings": {
    "my_type": {
      "dynamic_date_formats": ["MM/dd/yyyy"]
    }
  }
}
PUT my_index        //啟用數值型別檢測
{
  "mappings": {
    "my_type": {
      "numeric_detection": true
    }
  }
}

 

動態模板

動態模板將會根據條件判斷,應用到滿足條件的新增欄位上去。

應用條件包括:

  1. 用 match_mapping_type 來檢測新增欄位的資料型別是否滿足某種條件
  2. 用 match、unmatch 和 match_pattern 來判斷新增欄位的欄位名是否滿足某種條件
  3. 用 path_match 和 path_unmatch 來判斷新增欄位的完整路徑是否匹配某條件

動態模板以陣列的形式給出,陣列的每一個元素就是一個模板。每個模板都有各自的應用條件,一旦新增的欄位滿足某個模板,模板內容就會應用到該欄位上。

有兩個特殊的變數,在模板中可以運用:{name}、{dynamic_type}。前者表示原欄位的欄位名,後者標識原欄位被 ES 自動識別出來的資料型別。


"dynamic_templates": [                 //陣列,每個元素都是一個動態模板
    {
      "my_template_name": {            //動態模板名稱
        ...  match conditions ...      //應用條件判斷
        "mapping": { ... }             //對映設定
      }
    },
    ...                                //多個數組元素標識多個動態模板
  ]


PUT my_index
{
  "mappings": {
    "my_type": {
      "dynamic_templates": [
        {
          "named_analyzers": {
            "match_mapping_type": "string",
            "match": "*",
            "mapping": {
              "type": "string",
              "analyzer": "{name}"
            }
          }
        },
        {
          "no_doc_values": {
            "match_mapping_type":"*",
            "mapping": {
              "type": "{dynamic_type}",
              "doc_values": false
            }
          }
        }
      ]
    }
  }
}


索引模板

索引模板根據條件來判斷新建的索引(只應用到新建索引上)是否滿足某條件,並對其進行對映設定。

索引模板包含一些對索引的設定和對映設定。

在索引模板中有一個特殊變數可以運用:{index}。表示匹配上條件的原索引名稱。


PUT /_template/template_1
{
  "template": "te*",                          //判斷條件,判斷哪些索引將應用該模板
  "settings": {                               //索引設定
    "number_of_shards": 1
  },
  "mappings": {                               //對映設定
    "type1": {
      "_source": {
        "enabled": false
      },
      "properties": {
        "host_name": {
          "type": "string",
          "index": "not_analyzed"
        },
        "created_at": {
          "type": "date",
          "format": "EEE MMM dd HH:mm:ss Z YYYY"
        }
      }
    }
  }
}


參照:https://www.cnblogs.com/licongyu/category/819588.html

更多請參照:

          http://blog.csdn.net/napoay