Elasticsearch搜尋引擎第四篇-Mapping對映詳解
Mapping是什麼
mapping對映定義索引中有什麼欄位、欄位的型別等結構資訊。相當於資料庫中表結構定義,或 solr中的schema。因為lucene索引文件時需要知道該如何來索引儲存文件的欄位。 ES中支援手動定義對映和動態對映兩種方式。如下就是我們在建立索引時,手動自定義的對映:
PUT test { #定義索引名稱為test
"mappings" : { #對映定義
"_doc" : { #名為_doc的對映類別
"properties" : { #欄位定義
"field1" : { "type" : "text" } #名為field1的欄位
}
}
}
}
對映類別廢除說明
ES最先的設計是用索引類比關係型資料庫的資料庫,用mapping type 來類比表,一個索引中可以包含多個對映類別。這個類比存在一個嚴重的問題,就是當多個mapping type中存在同名欄位時(特別是同名欄位還是不同型別的),在一個索引中不好處理,因為搜尋引擎中只有 索引-文件的結構,不同對映類別的資料都是一個一個的文件(只是包含的欄位不一樣而已)
從6.0.0開始限定僅包含一個對映類別定義( “index.mapping.single_type”: true ),相容5.x中的多對映類別,從7.0開始將移除對映類別。為了與未來的規劃匹配,請現在將這個唯一的對映類別名定義為_doc
- PUT {index}/_doc/{id}
- POST {index}/_doc
Mapping對映例項:
PUT twitter {
"mappings": {
"_doc": {
"properties": {
"type": { "type": "keyword" },
"name": { "type": "text" },
"user_name": { "type": "keyword" },
"email": { "type": "keyword" },
"content" : { "type": "text" },
"tweeted_at": { "type": "date" }
}
}
}
}
欄位型別
text和keyword
這兩個欄位都是對應string型別的,但是有區別:
- text型別主要用於分詞,比如新聞標題、描述,不能進行排序和聚合
- keyword型別主要用於排序和聚合,比如新聞型別、商品類別 因此如果一個欄位被定義成了text型別,則就不能進行排序了,如果一個欄位既需要分詞、有需要排序或聚合,則可以將該欄位定義成Multi-fields
Multi-fields多重欄位
當我們需要對一個欄位進行多種不同方式的索引時,可以使用fields多重欄位定義。如一個字串欄位即需要進行text分詞索引,也需要進行keyword 關鍵字索引來支援排序、聚合,或需要用不同的分詞器進行分詞索引。 官網提供了一個例子,可以嘗試一下:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
}
PUT my_index/_doc/1
{
"city": "New York"
}
PUT my_index/_doc/2
{
"city": "York"
}
GET my_index/_search
{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}
- raw是一個自定義的多重欄位名
- 在進行排序查詢的時候,會將整個_source的內容進行排序,而不是對分詞後的結果進行排序
欄位其他屬性
PUT my_index {
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
- format屬性定義該時間欄位如何格式化
- 上述定義表示上傳的欄位date必須符合三種格式中的一種,ES內部會將時間全部轉換為long型別的毫秒數
元資料
Identity meta-fields
標識元欄位
- _index:該文件所屬的索引index
- _uid:_type和_id組合而成的複合字段
- _type:該文件的mapping type,以後統一為_doc
- _id:該文件的id,可以用上傳資料的唯一主鍵充當,也可以es內部自己生成
Document source meta-fields
文件源元欄位
- _source:是否儲存文件的原JSON物件,預設是true儲存
- _size:_source原JSON物件的大小,單位位元組數
Indexing meta-fields
- _all:複製文件的其他欄位值到這一個欄位上進行索引,預設禁用。6.0以後版本廢棄該欄位,改用copy-to
Routing meta-fields
- _routing:自定義的路由值,決定將文件路由到哪個分片上,預設是用_id,路由的計算方式:shard_num = hash(_routing) % num_primary_shards
動態對映
動態對映:ES中提供的重要特性,讓我們可以快速使用ES,而不需要先建立索引、定義對映。 如我們直接向ES提交文件進行索引:
PUT data/_doc/1 {
"count": 5
}
ES將自動為我們建立data索引、_doc 對映、型別為 long 的欄位 count。然後下次再索引文件時,當有新欄位時, ES將根據我們欄位的json的資料型別為我們自動加入欄位定義到mapping中。
欄位動態對映規則
Date detection 時間偵測
時間偵測date_detection預設是開啟的,當有一個內容提交上來時,ES會自動監測裡面的欄位是否符合時間格式,如果符合,則把它設定為時間型別。預設的時間格式dynamic_date_formats為:
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
官方示例:
PUT my_index/_doc/1
{
"create_date": "2015/09/02"
}
GET my_index/_mapping
create_date欄位會被自動新增為date型別,且format格式如下:
禁用時間偵測:
PUT my_index
{
"mappings": {
"_doc": {
"date_detection": false
}
}
}
自定義時間格式:
PUT my_index
{
"mappings": {
"_doc": {
"dynamic_date_formats": ["MM/dd/yyyy"]
}
}
}
Numeric detection 數值偵測
數值偵測預設是關閉的。數值偵測會對上傳上來的內容進行監測,會對數值型別的字串進行自動轉換,官網的例子如下:
PUT my_index
{
"mappings": {
"_doc": {
"numeric_detection": true
}
}
}
PUT my_index/_doc/1
{
"my_float": "1.0",
"my_integer": "1"
}