博客 / 詳情

返回

Elasticsearch的Mapping使用分析(es7官方文檔解讀)

@TOC


參考ES 7版本官方文檔
官方7.17文檔

挑了一些我覺得重要的點總結
如有謬誤,歡迎指正


mapping是什麼

在ES裏創建一個索引

PUT demo_index
{
    "mappings": {
        "dynamic": false
        "properties": {
            "demo_id": {
                "type": "text"
            }
        }
    }
}

上面的properties裏定義了字段demo_id,它的類型是text。dynamic選擇了false説明mapping不需要動態規則來匹配,這種情況下進行搜索時和普通的關係型數據庫搜索非常類似。

mapping類似於數據庫中的表結構定義,定義以下這些內容

  • 定義字段名稱
  • 定義字段數據類型
  • 字段、倒排索引的相關配置

但是和比如mysql這樣的數據相比還是有很多不同之處,搜索的字段類型可以提前定義好,也可以不定義讓ES來推測,也可在搜索的時候動態加入新字段。

GET /demo_index/_mapping

查看mapping

動態mapping

如果你想使用動態mapping就將上面提到的dynamic字段設置為true或者runtime

默認動態mapping

ES允許直接插入文檔,不需要提前定義類型、字段 ,當你查詢的時候會自動推測匹配顯示出來。

curl -X PUT "localhost:9200/data/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{ "count": 5 }
使用kibana的話直接PUT data/_doc/1 ... 就行

自動檢測類型和添加字段就是動態mapping,ES有默認的檢測規則,我們自己也可以定義自己的規則。

設計自己的mapping檢測模板

這一塊比較複雜

match_mapping_type
這個可以理解為根據字段默認檢測出來的類型進行匹配

用的官方文檔的案例:
可以看到當默認檢測出來的字段類型為integer時,將替換為long類型;如果檢測出來的類型為text或者keyword類型,將會替換為string類型。

PUT demo_index
{
  "mappings": {
    "dynamic_templates": [
      {
        "integers": {
          "match_mapping_type": "long",
          "mapping": {
            "type": "integer"
          }
        }
      },
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type":  "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    ]
  }
}

這張圖是在默認檢測下,從Json解析出來的數據類型和ES裏的數據的對應關係。需要注意的是dynamic字段設置為true和runtime的對應關係是略有不同的。
在這裏插入圖片描述

math/unmatch
根據字段名稱去匹配字段類型
如下,如果JSON解析出來的字段匹配long_*並且不匹配*_text,並且默認檢測出來的類型是long,那麼將其匹配為string類型。

PUT demo-index
{
  "mappings": {
    "dynamic_templates": [
      {
        "longs_as_strings": {
          "match_mapping_type": "string",
          "match":   "long_*",
          "unmatch": "*_text",
          "mapping": {
            "type": "long"
          }
        }
      }
    ]
  }
}

除了使用簡單的通配符來進行匹配之外,還可以使用正則表達式:

"match_pattern": "regex",
"match": "^profit_\d+$"

path_match/path_unmatch
這個是根據字段路徑匹配,我理解是用於匹配多層級的對象。
這裏產生的效果就是name對象去掉middle字段。

PUT demo-index
{
  "mappings": {
    "dynamic_templates": [
      {
        "full_name": {
          "path_match":   "name.*",
          "path_unmatch": "*.middle",
          "mapping": {
            "type":       "text",
            "copy_to":    "full_name"
          }
        }
      }
    ]
  }
}

PUT demo-index/_doc/1
{
  "name": {
    "first":  "John",
    "middle": "Winston",
    "last":   "Lennon"
  }
}
官方文檔裏的這個案例,還使用了copy_to,copy_to可以將值複製到另一個字段裏,是一個很實用的功能。

運行時字段

可以在mapping下設置runtime部分,使用script腳本來控制動態字段。
腳本可以訪問整個文檔,包括原始_source和mapping字段,腳本會查詢所有所需字段的值。

PUT demo-index/
{
  "mappings": {
    "runtime": {
      "day_of_week": {
        "type": "keyword",
        "script": {
          "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
        }
      }
    },
    "properties": {
      "@timestamp": {"type": "date"}
    }
  }
}

運行時字段在搜索時不會出現在_source裏,但是會有這個field,搜索時可以指定這個字段將其值搜索出來

>GET demo-index/_search
{
  "fields" : ["day_of_week"],
  "query": {
    "match": {
      ...
    }
  }
}

動態值就會顯示在查詢結果的hits裏的每個hit的fields裏

在某些情況下這個功能可以省去reindex, 比如發現mapping裏某字段希望修改它的數據類型,或者希望某些字段可以有另外的一種形式,在mapping中不太方便修改,方案可以有進行reindex,但是也可以通過這種動態形式拿到想獲取的值(讀時建模)。


當設置dynamic字段為runtime時,

PUT demo-index
{
  "mappings": {
    "dynamic": "runtime",
    "properties": {
      "@timestamp": {
        "type": "date"
      }
    }
  }
}

檢測到的新字段會自動加入到mapping的fields作為運行時字段。


也可以隨時更新或刪除運行時字段。要替換現有的運行時字段,在具有相同名稱的映射中添加一個新的運行時字段。設置null就可以刪除。

PUT demo-index/_mapping
{
 "runtime": {
   "day_of_week": null
 }
}

dynamic

dynamic用於控制是否動態添加新字段,可選項有:

  • true:新字段添加到mapping中(默認)。
  • runtime:新字段作為運行時字段添加到mapping中,這些字段不可索引,是_source在查詢時加載的。
  • false:忽略新字段,這些字段不會被索引或搜索,但仍會出現在_source返回的命令和字段中。這些字段不會添加到mapping中,必須顯式添加新字段。
  • strict:如果檢測到新字段,則會拋出異常。必須將新字段顯式添加到mapping中。

動態模式 (true)通俗來説就是往index裏寫入doc,doc裏的字段類型對應es裏的什麼數據類型,將會由默認推測規則來進行自動推測匹配(當然也可以自義定推測規則)。

不需要動態模式(false)的時候,可以按照自己的實際需求去設置mapping,插入doc的時候,字段與mapping裏的保持一致,如果doc添加了一個mapping裏不存在的字段,新字段不會被自動添加到mapping中,並且指定該字段進行查詢時,也無法匹配到結果,可以存儲、但是不能索引。

當dynamic設置為false時,顯式設置mapping,類似於關係型數據庫
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.