1. 程式人生 > >Elasticsearch搜尋引擎第四篇-Mapping對映詳解

Elasticsearch搜尋引擎第四篇-Mapping對映詳解

Mapping官網文件:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html

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" 
}