ElasticSearch中的對映

weixin_33686714發表於2018-11-04

         這裡講的ElasticSearch中的對映(schema mapping),是定義儲存和索引的文件型別和欄位的過程。這裡記住對映是一個動態過程。索引中的每一個文件都有一個型別,每種型別都有他自己的對映。對映起到定義文件欄位的資料型別的功能,這一功能其實是通過配置來定義欄位型別和該型別關聯的後設資料的關係來實現的。

對映型別

每個索引都有一個或多個對映型別,他的作用是在一個索引中將資料劃分為不同的邏輯組。每個對映型別都由元欄位和欄位組成。

1.元欄位

元欄位的作用是用來表示如何處理文件的後設資料。常見的元欄位有 _index,_type,_id,_source。 每個文件都有與之關聯的後設資料,元欄位是保證系統正常運轉的內建欄位。

2.欄位(或屬性)

欄位(或屬性)的作用是標識資料的型別。每個對映型別都包含與型別相關的欄位或者屬性列表。這裡注意如果是在同一個索引中的不同對映型別的相同欄位都具有相同的資料型別,意思是指在同一索引範圍中,只要對映欄位相同,那麼他就具有相同的對映型別。

欄位資料型別

ElasticSearch中的欄位資料型別包括基本的字串,日期,長整型long,雙精度double,布林型boolean,類似JSON的物件,IP,地理點和地理形狀(以後會對不同的型別做詳細解釋)。ElasticSearch可以顯式或者動態的設定對映,ElasticSearch的對映可以不事先定義,依靠動態對映,依靠新的索引文件,新的型別和欄位名可以自動新增。而新的型別對映又可以新增到頂級對映型別或者對映型別內部的物件和嵌入欄位。

對映型別在一個索引中是唯一的。也就是在同一個索引的不同型別中,相同的對映名稱一樣,那麼他們就具有相同的型別。

1. 核心資料型別

  • 字串資料型別

字串資料型別可以分為全文字和關鍵詞,同一欄位又可以同時設定全文字和關鍵字。全文字非常適合基於文字的相關性搜尋。

全文字的字串資料型別可以分詞,在索引執行之前通過分詞器將文字轉化為單詞表,這個操作就是ElasticSearch能在全文字中搜尋單詞的原理。這裡注意全文字的字串資料型別不用於排序且很少用於聚合。

關鍵詞的字串資料型別通常用來過濾,排序和聚合。並且不參與分詞。

  • 數字
  • 日期型別:注意json沒有日期型別,所以只能是字串,代表時間毫秒數的長整型,或者整型。可以使用雙豎線做多日期格式匹配。
  • boolean型別
  • base64編碼的二進位制值。不以預設方式儲存且不能被搜尋。

2. 複雜資料型別

  • 陣列

ElasticSearch沒有特定的陣列型別,但是每個欄位預設可以包含一個或者多個相同資料型別的值。

  • 物件型別

這裡指的物件型別採用的是json的天然分層特性。json文件內部可以包含物件。

  • 巢狀資料型別

3. 地理資料型別

這裡的地理資料型別說的是經緯度。從經緯度擴充套件一下幾個方面:

  • 查詢一定地理範圍內的資料
  • 聚合距離中心點一定距離的文件
  • 按照距離中心點的遠近進行排序
  • 整合地理資料到文件的相關性評分中

地理資料型別又分為:

  • 地理點
  • 地理形狀

3. 專門資料型別

  • IP
  • 單詞計數器:token_count

對映引數

用於欄位對映的引數。ElasticSearch中有大量的對映引數,這些引數的預設值都是最合適普遍場景的,但是如果想精通調優,需要理解這些對映引數。下面這些是選取的幾個典型對映引數。

1.analyzer

字串在索引和查詢時,都是被分析為一個個索引詞。通過合理的配置索引器可以大大提高在索引查詢時的效率。

2.boost

對欄位進行加權。預設值為1,如果設定了值則是所設定值的倍數。這裡注意在資料索引時最好不要加權。因為除非重新索引所有文件,不然加權值不會變。

3.coerce

強制型別轉換。如果值為false,在索引到不匹配型別的文件時就會丟棄

4.facat

facat代表多欄位,ElasticSearch允許你在一個欄位上設定兩種型別。假如你想在同一個欄位上進行兩種分析,一種用於搜尋,一種用於排序。或一個經過特定語言分析器來分析,而另一個只經過空白字元分析。那麼可以使用多欄位功能。該功能可以允許使用者只定義一個欄位型別就同時賦予該欄位兩種型別的型別。如下所示:

“name”:{ “type”:”string”, “property”:{ “facat”:{“type”:”string”,”index”:”not_anayzed"} } }

這樣就定義了兩個欄位,一個叫name,一個叫name.property,ElasticSearch會把name欄位中的值複製到name.property欄位中。

5.copy_to

ElasticSearch可以使用這個欄位來建立自定義的_all欄位。也就是說可以用多個欄位來合成一個欄位,把這個合成的欄位當做單個欄位來查詢。

6.doc_valus

倒排索引的列式儲存。這種結構很適合聚合,排序,指令碼操作。

動態索引

ElasticSearch可以在事先不設定索引結構的情況下,在文件直接插入到索引中時,系統會根據文件自動進行索引結構的動態對映。這樣做極大地簡化了索引的操作。

可以根據目的來指定動態對映生成的規則:

  • ElasticSearch中有個名為_default_的預設對映,這個預設對映相當於建立新對映型別的基礎對映。
  • 動態欄位對映。
  • 動態模板:也就是根據事先定義好的自定義規則來配置動態新增欄位的對映。

預設情況下,在文件中發現新的欄位的時候,ElasticSearch會自動根據一系列簡單的規則將新欄位新增到型別對映中。這些簡單的規則中,有些能解析形如日期的字串,有些能解析數字。其實ElasticSearch底層是通過定義文件的JSON來猜測文件結構和資料型別的,比如字串是被引號包圍,布林值使用特定的字元,數值則是一些數字型別。很明顯,這些簡單的規則有效而且易於理解。

那麼有沒有更加靈活的文件型別探測呢?比如被引號包圍的數字型別能不能被檢測為數值型別呢,答案是肯定的。ELasticsearch有種機制叫數值自動檢測,相關聯的設定為numeric_detection,該選項是預設關閉的,可以使用響應的put請求來開啟該選項。如果該選項開啟後,在索引資料時如果被引號包圍的資料為陣列型別,比如float型資料,那麼在索引完後,使用get方法來請求索引的_mapping_資料,你會發現剛才的數值型別的欄位的type為double了,當然如果索引的數值不是float,而是long型別資料,那麼_mapping中的型別也會變成long。

對映是如何xxx的

首先找到對映的入口。由於都是從rest的介面新增的對映,所以從rest包中入手肯定沒有錯。由於rest包中的類不多,檢視後知道了對映相關的類在indices包中。因為在對映都是依附在index上的,所以放到了indices包下。如下圖所示:

接下來找到入口,就分析是如何構造對映的。

  • 首先通過url中的index欄位構造一個初始的PutMappingRequest
  • 然後給該PutMappingRequest構造各種request中攜帶的引數
    • type:對映相關後設資料
    • source:對映相關後設資料
    • update_all_types:是否跨多個型別的對映欄位都更新
    • timeout:超時
    • master_timeout:如果在沒有發現master或者斷開與master連線情況下的超時值
    • expand_wildcards:索引配置相關,啟用的擴充套件萬用字元
    • ignore_unavailable:索引配置相關,snapshot,restore和index_settings操作使用此設定。
    • allow_no_indices:索引配置相關,
  • 最後通過NodeClient(實現了IndicesAdminClient介面)中的putMapping方法,將上一步構造好的action傳給ElasticSearch的client。

下圖顯示了實際執行對映操作的地方是NodeClientexecute方法

上面提到的PutMappingRequest初始化的引數如下圖所示,可看到我們put的資料都在source中:

然後會從actions中找到putmapping的action,action的型別為TransportAction。而該action的實際執行方法execute,該方法是當transport操作呼叫導致產生一個新的關聯任務時,實際使用的方法。

我們可以看到該方法使用預設好的actionName'indices:admin/mapping/put'和構造好的putMappingRequest註冊了一個task。然後分別在ActionListener中設定了成功和失敗的回撥方法。

由於我是單節點執行的ElasticSearch,所以在實際執行任務的類是TransportMasterNodeAction,這個類是需要在主節點上執行的操作的基類。在該類的doStart方法中,通過類TransportPutMappingAction和引數taskreqeust最眾到達實際的方法metaDataMappingService.putMapping中,如下圖所示;

至此前面的任務排程工作就都做完了,以後就是metaDataMappingService.PutMappingExecutor的工作了。

相關文章