@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,類似於關係型數據庫