天天看點

了解 mapping—Elastic Stack 實戰手冊

了解 mapping—Elastic Stack 實戰手冊
https://developer.aliyun.com/topic/download?id=1295 · 更多精彩内容,請下載下傳閱讀全本《Elastic Stack實戰手冊》 https://developer.aliyun.com/topic/download?id=1295 https://developer.aliyun.com/topic/es100 · 加入創作人行列,一起交流碰撞,參與技術圈年度盛事吧 https://developer.aliyun.com/topic/es100

創作人:歐陽楚才

映射(mapping)就像資料庫中的 Schema ,描述了文檔可能具有的字段或屬性、每個字段的資料類型,比如 text,keyword,integer 或 date ,以及 Lucene 是如何索引和存儲這些字段的。

核心簡單字段類型

Elasticsearch 支援如下簡單字段類型:

  • 字元串: text,keyword
  • 整數:byte,short,integer,long
  • 浮點數: float,double
  • 布爾型: boolean
  • 日期: date
更多的字段類型比如 geo_point,ip,nested 等可以在連結處檢視: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

當你索引一個包含新字段的文檔之前,未曾出現 Elasticsearch 會使用動态映射,通過 JSON 中基本資料類型,嘗試猜測字段類型,使用如下規則:

JSON 資料 字段類型
布爾型:true 或者 false boolean
整數:123 long
浮點數:123.45 double
字元串,有效日期:2021-05-01 date
字元串:foo bar text 和 keyword

注意:如果你通過引号 ( "123" ) 索引一個數字,它會被映射為字元串類型 text 和 keyword,而不是 long 。但如果這個字段已經映射為 long ,那麼 Elasticsearch 會嘗試将這個字元串轉化為 long (在 coerce 設定為 true 的情況下),如果無法轉化,則抛出一個異常。

檢視映射

通過 /_mapping ,我們可以檢視 Elasticsearch 在一個或多個索引中的映射。

Elasticsearch 文檔寫入示例:

PUT twitter/_doc/1
{
    "user": "kimchy",
    "post_date": "2009-11-15T13:12:00",
    "message": "Trying out Elasticsearch, so far so good?"
}

PUT twitter/_doc/2
{
    "user": "kimchy",
    "post_date": "2009-11-15T14:12:12",
    "message": "Another tweet, will it be indexed?"
}

PUT twitter/_doc/3
{
    "user": "elastic",
    "post_date": "2010-01-15T01:46:38",
    "message": "Building the site, should be kewl"
}           

檢視索引映射示例:

GET twitter/_mapping           

Elasticsearch 根據我們索引的文檔,為字段動态生成的映射:

{
  "twitter" : {
    "mappings" : {
      "properties" : {
        "message" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "post_date" : {
          "type" : "date"
        },
        "user" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}           

注意:錯誤的映射,例如将年齡字段映射為 text 類型,而不是 integer ,會導緻查詢出現令人困惑的結果。

檢查一下,而不是假設你的映射是正确的。

自定義字段映射

盡管在很多情況下基本字段資料類型已經夠用,但你經常需要為單獨字段自定義映射,特别是字元串字段。自定義映射允許你執行下面的操作:

  • 全文字元串字段和精确值字元串字段的差別
  • 使用特定語言分析器
  • 優化字段以适應部分比對
  • 指定自定義資料格式
  • 還有更多

字段最重要的屬性是 type 。

{
    "number_of_clicks": {
        "type": "integer"
    }
}           

字元串字段類型,包括全文字元串 text 和精确值字元串 keyword。

text 類型字段的最重要屬性是分析器 analyzer,預設 Elasticsearch 使用 Standard 分析器, 但你可以指定一個内置的分析器替代它,例如 whitespace 、 simple 、english、cjk:

{
   "message": {
    "type": "text",
    "analyzer": "cjk"
  }
}           

建立/更新映射

當你首次建立一個索引的時候,可以指定類型的映射。你也可以使用 /_mapping 更新映射。

我們可以更新一個映射來添加一個新字段,但不能更新一個現有的 mapping 把它的字段類型從一個變為另外一個,比如從 text 變為 keyword。我

們可以在維持現有 mapping 的情況下,把一個字段變成一個 multi-field 字段。

為了描述指定映射的兩種方式,我們先删除 twitter 索引:

DELETE twitter           

建立一個新索引,指定 message 字段使用 cjk 分析器:

PUT twitter
{
  "settings": {
    "number_of_shards": "5",
    "number_of_replicas": "1"
  },
  "mappings": {
    "properties": {
      "user": {
        "type": "keyword"
      },
      "post_date": {
        "type": "date"
      },
      "message": {
        "type": "text",
        "analyzer": "cjk"
      }
    }
  }
}           

通過消息體中指定的 mappings 建立了索引映射,索引設定 settings 中通過 number_of_shards 指定分片數,number_of_replicas 指定副本數。

給映射增加一個新的名為 tag 的 keyword 類型字段,使用 _mapping :

PUT twitter/_mapping
{
  "properties": {
    "tag": {
      "type": "keyword"
    }
  }
}           

我們不需要再次列出所有已存在的字段,因為無論如何我們都無法改變它們,新字段已經被合并到存在的映射中。

測試映射

可以使用 analyze API 測試字元串字段的映射,比較下面兩個請求的輸出:

GET /twitter/_analyze
{
  "field": "message",
  "text": "搜尋引擎" 
}

GET /twitter/_analyze
{
  "field": "tag",
  "text": "搜尋引擎" 
}           

消息體裡面傳入我們想要分析的文本。message 字段産生 3 個詞條 ”搜尋“、”索引” 和 ”引擎“, tag 字段産生單獨的詞條”搜尋引擎“,換句話說,我們的映射正常工作。