Elasticsearch mapping

  • 2022 年 11 月 4 日
  • 筆記

Elasticsearch mapping

本篇主要介紹一下 Elasticsearch mapping 的概念, 它是什麼 以及如何自定義它, 並且再介紹一下 dynamic 的機制

image-20221101151025669

如果把 Elasticsearch中的mapping 對比到 mysql 中 就是 mysql中的 表的 scheme , 就是表的定義結構,

正常在 關係型資料庫mysql中 需要先把表的scheme 定義好 再插入數據, 並且 你無法插入未在scheme 中定義的欄位 , 而 es 中 可以在你未給索引定義 mapping 的時候 自動幫你創建 mapping , 並且你也可以通過 dynamic 來控制是否允許靈活動態的 添加 mapping中的屬性

1.什麼是Mapping

  • Mapping 類似 mysql 中的 schema 的定義,就是定義索引屬性欄位的

    • 定義索引中欄位的名稱
    • 定義索引中欄位的數據類型 , 如 text , long , keyword….
    • 定義索引中欄位的的倒排索引相關配置 ( Analyzer…)
  • 一個Mapping 屬於一個索引的Type

    • 每個文檔都屬於一個Type
    • 一個Type有一個Mapping 定義
    • es7.0開始, 在Mapping中不需要指定 Type資訊, 因為7.0之後只有_doc Type

2.es 自動創建mapping

當我們去創建一個 索引的時候 未指定 mapping , es會默認幫這個索引創建一個 mapping

創建一個 索引並且索引一條數據

PUT blog/_doc/1
{
  "name": "es mapping",
  "type": "es",
  "desc": "es mapping desc",
  "author": "johnny",
  "word_count": 50,
  "create_time": "2022-10-31"
}
GET blog/_mapping  # 查看一個 es自動生成的 mapping

image-20221101132257644

從上面可以看出來 屬性都被es 自動創建了 對應的mapping , 包括每個屬性的type類型等, 那它為什麼會這樣轉化的,什麼時候是 text, 什麼時候是 long 下面就來介紹 es 中mapping 的 類型自動識別

3. mapping 類型自動識別

JSON類型 Elasticsearch 類型
字元串 1.匹配日期格式 會設置成Date
2.匹配數字 設置成 float 或者 long ,該選項默認關閉的
3.設置成Text , 並且添加 keyword 子欄位
整數 long
浮點數 float
布爾值 boolean
對象 object
數組 由第一個非空數值的類型所定義 .如 [“jack”,”johnny”] 則類型為 Text
空值 忽略 ???
我實驗的版本里7.18 , 如果設置null 會被自動定義為Text , 具體不太清楚

4. 自定義創建mapping

除了上面的介紹的 es 自動創建 mapping 外, 還可以自定義 索引的mapping , 更加靈活和符合業務需求等等.

注意以前的版本需要在 mappings 下面還有一層 type , 如 mappings: { “_doc” : { “properties” : {xxx} }} 但是7.0之後 type就不需要了

PUT blog_info
{
  "mappings": {
      "properties": {
        "blog_name": {
          "type": "keyword"
        },
        "blog_desc": {
          "type": "text"
        },
        "blog_word_count": {
          "type": "long"
        },
        "create_time": {
          "type": "date"
        }
      }
    }
}

其中text和keyword類型,text類型的欄位在新增或修改文檔時會自動分詞, 而keyword 不會,它會保存插入的原始文本

索引一條數據

PUT blog_info/_doc/1
{
  "blog_name": "es mapping",
  "blog_desc": "es mapping desc",
  "blog_word_count": 12,
  "blog_auther": "johnny",
  "create_time": "2022-10-31"
}

5. mapping 屬性設置analyzer 分詞器

默認分詞器 standard , 它會把中文一個個拆開,肯定是不適合的,如果是索引中文的資訊, 需要設置欄位的分詞器,

PUT blog_info
{
  "mappings": {
      "properties": {
        "blog_desc": {
          "type": "text",
          "analyzer": "ik_smart" //設置這個欄位的分詞器 
        }
      }
    }
}

大部分分詞器是需要以es 中插件的方式 安裝的 ,後續會出一篇專門的 analyzer 分詞器

6. mapping 屬性設置 boost 權重

在es搜索的時候 會有一個相關性算分的過程 , 如果不設置 每個欄位的默認boost 權重為1.0 , 如果希望加大 按照廣告投放金額的分 那麼可以設置boost 以提高搜索 自然就排在前面了

PUT blog_info
{
  "mappings": {
      "properties": {
        "put_amount": {
          "type": "text",
          "boost": "5" 
        }
      }
    }
}

7. mapping 屬性設置 copy_to

該屬性允許多個欄位 copy 到指定的欄位, 可以進行搜索這個欄位,但是_source 中是不顯示的

PUT peope
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text",
        "copy_to": "full_name"
      },
      "last_name":{
        "type": "text",
        "copy_to": "full_name" // copy_to 指定欄位
      },
      "full_name":{
        "type": "text"
      }
    }
  }
}
GET peope/_search?q=full_name:johnny  //使用 full_name 去搜索

//可以看到 並沒有 full_name 的返回 但是可以通過它去搜索
"_source" : {
   "first_name" : "johnny",
   "last_name" : "qiang"
}

8. mapping 屬性設置 index

通過給 屬性設置 index 來控制該 欄位是否 參與 索引, 默認 true , 如果index 設置為false 那麼 不能記錄索引 並且不可以搜索

PUT peope
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text",
        "index": false //設置 index false
      },
      "last_name":{
        "type": "text"
      }
    }
  }
}

POST peope/_doc
{
  "first_name": "johnny is good name",
  "last_name": "qiang"
}

注意 url-search 搜不到但是不報錯, 而 requestbody 查詢 index false 的欄位 會報錯

GET peope/_search?q=first_name:johnny //搜索不到數據 因為 

//"hits" : [ ] 

GET peope/_search?q=last_name:johnny // 可以看到由於 last_name 默認index 了 所以可以搜索到

//
//    "hits" : [
//      {
//        "_index" : "peope",
//        "_type" : "_doc",
//        "_id" : "vobiMYQB4x9Wk60f2F21",
//        "_score" : 0.2876821,
//        "_source" : {
//          "first_name" : "johnny is good name",
//          "last_name" : "johnny is good name"
//        }
//      }
//    ]

GET peope/_search
{
  "query": {
    "match": {
      "first_name": "johnny"
    }
  }
}
// 拋錯400 Cannot search on field [first_name] since it is not indexed.

9. mapping 設置 屬性 null_value 默認值

null_value:當欄位遇到null值時候的處理策略(欄位為null時候是不能被搜索的,也就是說,text類型的欄位不能使用該屬性,可以使用在keyword 欄位上),設置該值後可以用你設置的值替換null值,這點可類比mysql中的”default”設置默認值, 但是也有點不一樣, 後續就可以使用你設置的這個 null_value 去搜索, 但是檢索出來的數據_source 中 還是展示 null

PUT peope
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "keyword",
        "null_value": "default" // 設置當 文檔的first_name 欄位為null時候 轉成default 去創建倒排索引
      },
      "last_name":{
        "type": "text"
      }
    }
  }
}

POST peope/_doc
{
  "first_name": null, //設置null值
  "last_name": "johnny is good name",
  "full_name": "johnny is good name"
}

GET peope/_search?q=first_name:default //根據 null_value 設置的值去搜索,查詢出來還是原來的null

// {
//        "_index" : "peope",
//        "_type" : "_doc",
//        "_id" : "xob-MYQB4x9Wk60fVF1_",
//        "_score" : 0.2876821,
//        "_source" : {
//          "first_name" : null,  
//          "last_name" : "johnny is good name",
//          "full_name" : "johnny is good name"
//        }
// }

10. mapping 設置 dynamic

dynamic 是否允許動態新增欄位

  • true : 允許動態新增欄位 同時mapping 被更新 文檔可被索引
  • false: 不允許動態新增欄位 , mapping 不會被更新, 欄位不能被索引, 但是數據可以入庫並且資訊會出現在 _source 中
  • strict : 不允許寫入, 直接報錯

對於已經存在的欄位 一旦又數據寫入,就不能進行修改欄位定義了,因為 底層Lucene不允許修改, 如果希望修改欄位類型,必須 reindex 重建索引

10.1 dynamic false

PUT peope
{
  "mappings": {
    "dynamic": false, // 設置在索引上的 而不是對應的欄位上的 
    "properties": {
      "first_name": {
        "type": "text"
      },
      "last_name":{
        "type": "text"
      }
    }
  }
}

POST peope/_doc //dynamic false 可以入庫文檔數據
{
  "first_name": "johnny is good name",
  "last_name": "johnny is good name",
  "full_name": "johnny is good name"
}


GET peope/_search?q=full_name:johnny //嘗試通過 新增的欄位去搜索
// "hits" : [ ]

GET peope/_search?q=first_name:johnny // 可以搜到數據, 並且_source 中可以看到新增的欄位
//
//    "hits" : [
//      {
//        "_index" : "peope",
//        "_type" : "_doc",
//        "_id" : "vobiMYQB4x9Wk60f2F21",
//        "_score" : 0.2876821,
//        "_source" : {
//          "first_name" : "johnny is good name",
//          "last_name" : "johnny is good name",
//          "full_name" : "johnny is good name" 
//        }
//      }
//    ]

10.2 dynamic strict

strict : 嚴格模式 , 不允許 動態新增欄位的

PUT peope
{
  "mappings": {
    "dynamic": "strict",
    "properties": {
      "first_name": {
        "type": "text"
      },
      "last_name":{
        "type": "text"
      }
    }
  }
}
POST peope/_doc //直接拋錯
{
  "first_name": "johnny is good name",
  "last_name": "johnny is good name",
  "full_name": "johnny is good name"
}
// 400 mapping set to strict, dynamic introduction of [full_name] within [_doc] is not allowed

總結

本篇非常詳細介紹了 Elasticsearch中 mapping , 介紹了mapping它是什麼, 自動創建mapping的機制 , 自定義mapping 中各種參數設置. 一起來學習鞏固吧.

歡迎大家訪問 個人部落格 Johnny小屋
歡迎關注個人公眾號

歡迎關注個人公眾號