一文搞懂 Elasticsearch 之 Mapping

来源:https://www.cnblogs.com/wupeixuan/archive/2020/03/18/12514843.html
-Advertisement-
Play Games

作為 Elasticsearch 的“表結構定義”的 Mapping,你可能需要瞭解下! ...


這篇文章主要介紹 Mapping、Dynamic Mapping 以及 ElasticSearch 是如何自動判斷欄位的類型,同時介紹 Mapping 的相關參數設置。

首先來看下什麼是 Mapping:

什麼是 Mapping?

一篇文章帶你搞定 ElasticSearch 術語中,我們講到了 Mapping 類似於資料庫中的表結構定義 schema,它有以下幾個作用:

  • 定義索引中的欄位的名稱
  • 定義欄位的數據類型,比如字元串、數字、布爾
  • 欄位,倒排索引的相關配置,比如設置某個欄位為不被索引、記錄 position 等

在 ES 早期版本,一個索引下是可以有多個 Type 的,從 7.0 開始,一個索引只有一個 Type,也可以說一個 Type 有一個 Mapping 定義。

在瞭解了什麼是 Mapping 之後,接下來對 Mapping 的設置做下介紹:

Mapping 設置

PUT users
{
    "mappings": {
        "_doc": {
            "dynamic": false
        }
    }
}

在創建一個索引的時候,可以對 dynamic 進行設置,可以設成 falsetrue 或者 strict

Dynamic Mappings 設置

比如一個新的文檔,這個文檔包含一個欄位,當 Dynamic 設置為 true 時,這個文檔可以被索引進 ES,這個欄位也可以被索引,也就是這個欄位可以被搜索,Mapping 也同時被更新;當 dynamic 被設置為 false 時候,存在新增欄位的數據寫入,該數據可以被索引,但是新增欄位被丟棄;當設置成 strict 模式時候,數據寫入直接出錯。

另外還有 index 參數,用來控制當前欄位是否被索引,預設為 true,如果設為 false,則該欄位不可被搜索。

參數 index_options 用於控制倒排索引記錄的內容,有如下 4 種配置:

  • doc:只記錄 doc id
  • freqs:記錄 doc idterm frequencies
  • positions:記錄 doc idterm frequenciesterm position
  • offsets:記錄 doc idterm frequenciesterm positioncharacter offects

另外,text 類型預設配置為 positions,其他類型預設為 doc,記錄內容越多,占用存儲空間越大。

null_value 主要是當欄位遇到 null 值時的處理策略,預設為 NULL,即空值,此時 ES 會預設忽略該值,可以通過設定該值設定欄位的預設值,另外只有 KeyWord 類型支持設定 null_value

copy_to 作用是將該欄位的值複製到目標欄位,實現類似 _all 的作用,它不會出現在 _source 中,只用來搜索。

除了上述介紹的參數,還有許多參數,大家感興趣的可以在官方文檔中進行查看。

在學習了 Mapping 的設置之後,讓我們來看下欄位的數據類型有哪些吧!

欄位數據類型

ES 欄位類型類似於 MySQL 中的欄位類型,ES 欄位類型主要有:核心類型、複雜類型、地理類型以及特殊類型,具體的數據類型如下圖所示:

欄位數據類型

核心類型

從圖中可以看出核心類型可以劃分為字元串類型、數字類型、日期類型、布爾類型、基於 BASE64 的二進位類型、範圍類型。

字元串類型

其中,在 ES 7.x 有兩種字元串類型:textkeyword,在 ES 5.x 之後 string 類型已經不再支持了。

text 類型適用於需要被全文檢索的欄位,例如新聞正文、郵件內容等比較長的文字,text 類型會被 Lucene 分詞器(Analyzer)處理為一個個詞項,並使用 Lucene 倒排索引存儲,text 欄位不能被用於排序,如果需要使用該類型的欄位只需要在定義映射時指定 JSON 中對應欄位的 typetext

keyword 適合簡短、結構化字元串,例如主機名、姓名、商品名稱等,可以用於過濾、排序、聚合檢索,也可以用於精確查詢

數字類型

數字類型分為 long、integer、short、byte、double、float、half_float、scaled_float

數字類型的欄位在滿足需求的前提下應當儘量選擇範圍較小的數據類型,欄位長度越短,搜索效率越高,對於浮點數,可以優先考慮使用 scaled_float 類型,該類型可以通過縮放因數來精確浮點數,例如 12.34 可以轉換為 1234 來存儲。

日期類型

在 ES 中日期可以為以下形式:

  • 格式化的日期字元串,例如 2020-03-17 00:00、2020/03/17
  • 時間戳(和 1970-01-01 00:00:00 UTC 的差值),單位毫秒或者秒

即使是格式化的日期字元串,ES 底層依然採用的是時間戳的形式存儲。

布爾類型

JSON 文檔中同樣存在布爾類型,不過 JSON 字元串類型也可以被 ES 轉換為布爾類型存儲,前提是字元串的取值為 true 或者 false,布爾類型常用於檢索中的過濾條件。

二進位類型

二進位類型 binary 接受 BASE64 編碼的字元串,預設 store 屬性為 false,並且不可以被搜索。

範圍類型

範圍類型可以用來表達一個數據的區間,可以分為5種:integer_range、float_range、long_range、double_range 以及 date_range

複雜類型

複合類型主要有對象類型(object)和嵌套類型(nested):

對象類型

JSON 字元串允許嵌套對象,一個文檔可以嵌套多個、多層對象。可以通過對象類型來存儲二級文檔,不過由於 Lucene 並沒有內部對象的概念,ES 會將原 JSON 文檔扁平化,例如文檔:

{
    "name": {
        "first": "wu",
        "last": "px"
    }
}

實際上 ES 會將其轉換為以下格式,並通過 Lucene 存儲,即使 nameobject 類型:

{
    "name.first": "wu",
    "name.last": "px"
}

嵌套類型

嵌套類型可以看成是一個特殊的對象類型,可以讓對象數組獨立檢索,例如文檔:

{
  "group": "users",
  "username": [
    { "first": "wu", "last": "px"},
    { "first": "hu", "last": "xy"},
    { "first": "wu", "last": "mx"}
  ]
}

username 欄位是一個 JSON 數組,並且每個數組對象都是一個 JSON 對象。如果將 username 設置為對象類型,那麼 ES 會將其轉換為:

{
  "group": "users",
  "username.first": ["wu", "hu", "wu"],
  "username.last": ["px", "xy", "mx"]
}

可以看出轉換後的 JSON 文檔中 firstlast 的關聯丟失了,如果嘗試搜索 firstwulastxy 的文檔,那麼成功會檢索出上述文檔,但是 wuxy 在原 JSON 文檔中並不屬於同一個 JSON 對象,應當是不匹配的,即檢索不出任何結果。

嵌套類型就是為瞭解決這種問題的,嵌套類型將數組中的每個 JSON 對象作為獨立的隱藏文檔來存儲,每個嵌套的對象都能夠獨立地被搜索,所以上述案例中雖然錶面上只有 1 個文檔,但實際上是存儲了 4 個文檔。

地理類型

地理類型欄位分為兩種:經緯度類型和地理區域類型:

經緯度類型

經緯度類型欄位(geo_point)可以存儲經緯度相關信息,通過地理類型的欄位,可以用來實現諸如查找在指定地理區域內相關的文檔、根據距離排序、根據地理位置修改評分規則等需求。

地理區域類型

經緯度類型可以表達一個點,而 geo_shape 類型可以表達一塊地理區域,區域的形狀可以是任意多邊形,也可以是點、線、面、多點、多線、多面等幾何類型。

特殊類型

特殊類型包括 IP 類型、過濾器類型、Join 類型、別名類型等,在這裡簡單介紹下 IP 類型和 Join 類型,其他特殊類型可以查看官方文檔。

IP 類型

IP 類型的欄位可以用來存儲 IPv4 或者 IPv6 地址,如果需要存儲 IP 類型的欄位,需要手動定義映射:

{
  "mappings": {
    "properties": {
      "my_ip": {
        "type": "ip"
      }
    }
  }
}

Join 類型

Join 類型是 ES 6.x 引入的類型,以取代淘汰的 _parent 元欄位,用來實現文檔的一對一、一對多的關係,主要用來做父子查詢。

Join 類型的 Mapping 如下:

PUT my_index
{
  "mappings": {
    "properties": {
      "my_join_field": { 
        "type": "join",
        "relations": {
          "question": "answer" 
        }
      }
    }
  }
}

其中,my_join_field 為 Join 類型欄位的名稱;relations 指定關係:questionanswer 的父類。

例如定義一個 ID 為 1 的父文檔:

PUT my_join_index/1?refresh
{
  "text": "This is a question",
  "my_join_field": "question" 
}

接下來定義一個子文檔,該文檔指定了父文檔 ID 為 1:

PUT my_join_index/_doc/2?routing=1&refresh 
{
  "text": "This is an answer",
  "my_join_field": {
    "name": "answer", 
    "parent": "1" 
  }
}

再瞭解完欄位數據類型後,再讓我們看下什麼是 Dynamic Mapping?

什麼是 Dynamic Mapping?

Dynamic Mapping 機制使我們不需要手動定義 Mapping,ES 會自動根據文檔信息來判斷欄位合適的類型,但是有時候也會推算的不對,比如地理位置信息有可能會判斷為 Text,當類型如果設置不對時,會導致一些功能無法正常工作,比如 Range 查詢。

類型自動識別

ES 類型的自動識別是基於 JSON 的格式,如果輸入的是 JSON 是字元串且格式為日期格式,ES 會自動設置成 Date 類型;當輸入的字元串是數字的時候,ES 預設會當成字元串來處理,可以通過設置來轉換成合適的類型;如果輸入的是 Text 欄位的時候,ES 會自動增加 keyword 子欄位,還有一些自動識別如下圖所示:

類型自動識別

下麵我們通過一個例子是看看是怎麼類型自動識別的,輸入如下請求,創建索引:

PUT /mapping_test/_doc/1
{
  "uid": "123",
  "username": "wupx",
  "birth": "2020-03-16",
  "married": false,
  "age": 18,
  "heigh": 180,
  "tags": [
    "java",
    "boy"
  ],
  "money": 999.9
}

然後使用 GET /mapping_test/_mapping 查看,結果如下圖所示:

可以從結果中看出,ES 會根據文檔信息自動推算出合適的類型。

哦豁,萬一我想修改 Mapping 的欄位類型,能否更改呢?讓我們分以下兩種情況來探究下:

修改 Mapping 欄位類型?

如果是新增加的欄位,根據 Dynamic 的設置分為以下三種狀況:

  • 當 Dynamic 設置為 true 時,一旦有新增欄位的文檔寫入,Mapping 也同時被更新。
  • 當 Dynamic 設置為 false 時,索引的 Mapping 是不會被更新的,新增欄位的數據無法被索引,也就是無法被搜索,但是信息會出現在 _source 中。
  • 當 Dynamic 設置為 strict 時,文檔寫入會失敗。

另外一種是欄位已經存在,這種情況下,ES 是不允許修改欄位的類型的,因為 ES 是根據 Lucene 實現的倒排索引,一旦生成後就不允許修改,如果希望改變欄位類型,必須使用 Reindex API 重建索引。

不能修改的原因是如果修改了欄位的數據類型,會導致已被索引的無法被搜索,但是如果是增加新的欄位,就不會有這樣的影響。

總結

本文主要介紹了 Mapping 和 Dynamic Mapping,同時對欄位類型做了詳細介紹,也介紹了在 ES 中是如何對欄位類型做推算的,瞭解了 Mapping 的相關參數設置。

在公眾號【武培軒】回覆【es】獲取思維導圖以及源代碼。

參考文獻

《Elasticsearch技術解析與實戰》

Elastic Stack從入門到實踐

Elasticsearch核心技術與實戰

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/mapping.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大家在做小程式或者客戶端開發的時候肯定會想使得數據進行聯網,但這樣就必須有對應的後臺伺服器以及資料庫,再加上linux運維等各種細節,往往會對新手比較勸退,在這裡給大家推薦一種 bass(後端即服務) ,不僅支持小程式,還支持網頁端,android,ios多平臺調用,支持Java,python,c ...
  • 1 雙擊 運行 Xming 軟體 軟體下載連接 Xming 2 securecrt 打開 X11 轉發 3 確認 ssh配置文件開啟 X11 轉發 [root@Cobbler-ysw ysw]# cat /etc/ssh/sshd_config | grep X11Forwarding X11For ...
  • vscode 1.42.1 OS: windows 7 x64 1. vscode, cpp extension 本文直接跳過 vscode 安裝, Cpp tools 安裝 2. MinGw 安裝及配置 下載 "MinGW Minimalist GNU for Windows" 安裝過程 安裝所需 ...
  • 一 Kubernetes API Server原理1.1 API Server功能Kubernetes API Server的核心功能是提供Kubernetes各類資源對象(如Pod、RC、Service等)的增、刪、改、查及Watch等HTTP Rest介面,成為集群內各個功能模塊之間數據交互和通... ...
  • (1)RAID0:提升讀寫速度,但數據部備份 (2)RAID1:讀寫速度沒有要求,增加數據安全性 (3)RAID5:至少三塊,增加奇偶校驗位,一塊硬碟損壞,數據還能恢復,數據並沒有備份 (4)RAID10:0和1的結合,至少四個硬碟來組建,繼承了0的高讀寫速度和1的數據安全性 虛擬機添加四塊硬碟。3 ...
  • (1) lsblk 查看硬碟信息 fdisk /dev/sdb 更改寫入磁碟信息 輸入 n 命令新建磁碟分區,輸入p 命令新建主分區sdb1,磁碟大小為3G 輸入 n 命令新建磁碟分區,輸入p 命令新建主分區sdb2,磁碟大小為2G 輸入 n 命令新建磁碟分區,輸入e命令新建擴展分區sdb3,磁碟大 ...
  • 1、首先查看伺服器系統內核,docker環境要求的內核必須在3.10或以上 執行:uname -r 版本為3.10,可安裝docker 2、切到root用戶下,更新yum源,使yum源為最新狀態 執行:yum update 3、安裝docker依賴的軟體包,yum-util 提供yum-config ...
  • ISSI IS62WV51216ALL/IS62WV51216BLL是高速8M位靜態RAM,組織為512K字乘16位。它是使用ISSI的高性能CMOS技術製造的。這種高度可靠的工藝加上創新的電路設計技術,可生產出高性能和低功耗的設備。 當CS1為HIGH(取消選擇)或CS2為LOW(取消選擇)或CS ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...