【Elasticsearch系列之一】ES基本概念
- 2020 年 4 月 7 日
- 筆記
1、Near Realtime 近實時
ES 是一個近實時的搜索平台,當一個文檔寫入Lucene後是不能被立即查詢到的。Elasticsearch提供了一個refresh操作,會定時地調用lucene的reopen(新版本為openIfChanged)為記憶體中新寫入的數據生成一個新的segment,此時被處理的文檔均可以被檢索到。refresh操作的時間間隔由refresh_interval參數控制,默認為1s, 可以在寫入請求中帶上refresh表示寫入後立即refresh,另外還可以調用refresh API顯式refresh,例如:
POST /refresh #刷新所有索引 POST /my_logs/_refresh #刷新my_logs索引
注意:為了提高寫性能,騰訊雲Elasticsearch的refresh_interval參數的默認值設置的是30s, 要30s才能查到數據,客戶可以設置 refresh_interval 參數來把30s變成1s, 在kibana里寫入語法修改:
PUT /your_index/_settings { "index" : { "refresh_interval" : 1s } }
在生產環境中需要根據具體應用場景來調整refresh_interval 參數值,如果設置的過小,就會頻繁的重載索引文件,導致請求變慢。建議對於搜索結果實時性不高的場景(日誌檢索等),可以適當增加refresh_interval參數值。
2、Cluster 集群
集群(cluster)是一組具有相同cluster.name的節點集合,他們協同工作,共同存儲了所有數據,並提供了跨節點的聯合索引和搜索功能,當然一個節點也可以組成一個集群,當有節點加入集群中或者從集群中移除節點時,集群將會重新平均分布所有的數據。
2.1、集群健康狀態
集群狀態通過 綠,黃,紅 來標識:
- 綠色 – 一切都很好(集群功能齊全)。
- 黃色 – 所有數據均可用,但尚未分配一些副本(集群功能齊全)。
- 紅色 – 某些數據由於某種原因不可用(集群部分功能)。
注意:當群集為紅色時,它將繼續提供來自可用分片的搜索請求,但您可能需要儘快修復它,因為存在未分配的分片。
要檢查群集運行狀況,我們可以在 Kibana 控制台中運行以下命令:
GET /_cluster/health
得到如下資訊:
{ "cluster_name" : "es-p2wje7t7", "status" : "green", "timed_out" : false, "number_of_nodes" : 5, "number_of_data_nodes" : 2, "active_primary_shards" : 35, "active_shards" : 70, "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 0, "delayed_unassigned_shards" : 0, "number_of_pending_tasks" : 0, "number_of_in_flight_fetch" : 0, "task_max_waiting_in_queue_millis" : 0, "active_shards_percent_as_number" : 100.0 }
2.2、Master主節點
node.master設置為true(默認)的 節點,使其有資格被選為集群的Master節點。Master節點不負責數據的索引和檢索,所以負載較輕。當Master節點失聯或者掛掉的時候,ES集群會自動從其他Master節點選舉出一個Leader。
為保證數據得一致性,只有Master節點可以修改信,Master節點負責同步集群狀態資訊如下:
1) 所有節點資訊;
2) 所有索引即其 Mapping 和 Setting 資訊;
3) 所有分片路由資訊;
4) Master節點負責集群相關的操作,例如創建或刪除索引,跟蹤哪些節點是集群的一部分,以及決定將哪些分片分配給哪些節點。
建議:
因為索引和搜索數據都是CPU,記憶體和I/O密集型工作,可能會對節點資源造成壓力,為確保Master節點穩定且不受壓力,在實際生產環境中或較大的群集中,最好分割專用Master節點和專用Data節點之間的角色。
雖然Master節點也可以為協調節點,並將搜索和索引請求從客戶端路由到數據節點,但為了集群的穩定性,建議用專用Master節點。創建專用的Master節點參數如下:
node.master: true node.data: false node.ingest: false
如果使用 kibana 來作為視圖操作工具的話,我們只需在kibana.yml的配置文件中,將elasticsearch.url: "http://localhost:9200"設置為Master節點就可以了,通過Master節點,ES會自動關聯查詢所有節點和分片以及副本的資訊。所以 kibana 一般都和主節點在同一台伺服器上。
對用戶的訪問是透明的,我們可以將請求發送到集群中的任何節點 ,包括主節點。 每個節點都知道任意文檔所處的位置,並且能夠將我們的請求直接轉發到存儲我們所需文檔的節點。 無論我們將請求發送到哪個節點,它都能負責從各個包含我們所需文檔的節點收集回數據,並將最終結果返回給客戶端。
2.3、發現機制
發現機制負責發現集群中的節點,以及選擇Master節點。每次集群狀態發生更改時,集群中的其他節點都會知道狀態(具體方式取決於使用的是哪一種發現機制)。
ES目前主要推薦的自動發現機制,有如下幾種:
1) Azure classic discovery 插件方式,多播;
2) EC2 discovery 插件方式,多播;
3) Google Compute Engine (GCE) discovery 插件方式,多播;
4) Zen discovery 默認實現,多播/單播。
Zen Discovery 是 ES 默認內建發現機制。它提供單播和多播的發現方式,並且可以擴展為通過插件支援雲環境和其他形式的發現。所以我們接下來重點介紹下 Zen Discovery是如何在Elasticsearch中使用的。
集群是由相同cluster.name
的節點組成的。當您在同一台機器上啟動了第二個節點時,只要它和第一個節點有同樣的 cluster.name
配置,它就會自動發現集群並加入到其中。但是在不同機器上啟動節點的時候,為了加入到同一集群,您需要配置一個可連接到的單播主機列表。
單播主機列表通過discovery.zen.ping.unicast.hosts
來配置。這個配置在 elasticsearch.yml 文件中,具體配置如下:
discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]
具體的值是一個主機數組或逗號分隔的字元串。每個值應採用host:port或host的形式(其中port默認為設置transport.profiles.default.port,如果未設置則返回transport.tcp.port)。注意在ES 7.0.0中,官方文檔明確指出,和集群發現(Discovery)有關的配置主要由下面兩個:
discovery.seed_hosts: ["10.10.3.9", "10.10.3.16", "10.10.3.2"]
#當第一次啟動全新Elasticsearch集群時,會有一個集群引導(cluster bootstrapping)步驟,這個步驟會確定一個在第一次選舉中投票被計數的、並且可以成為 master節點的集合 cluster.initial_master_nodes: ["Intel-node-1", "Intel-node-2", "Intel-node-3"]
另外,discovery.zen.ping.unicast.resolve_timeout 配置在每輪ping操作中等待DNS查找的時間。需要指定時間單位,默認為5秒。
單播發現(unicast discovery)應用 transport 模組實現發現(discovery)。使用單播,您可以為 Elasticsearch 提供一些它應該去嘗試連接的節點列表。當一個節點聯繫到單播列表中的成員時,它就會得到整個集群所有節點的狀態,然後它會聯繫 master節點,並加入集群。這意味著您的單播列表不需要包含集群中的所有節點,它只是需要足夠的節點,當一個新節點聯繫上其中一個並且能正常通訊就可以了。如果您使用 master 候選節點作為單播列表,只要列出三個就可以了。
Elasticsearch 官方推薦我們使用單播(默認)代替組播,雖然組播仍然作為插件提供, 但不建議在生產環境使用,否則可能導致一個節點意外收到了組播訊號,而錯誤的加入到生產環境中。
2.3、選舉Master節點
選舉Mater節點會執行ping,其他節點加入某個集群也會執行ping,這個過程是自動執行的。通過配置discovery.zen.ping_timeout來控制節點加入某個集群或者開始選舉的響應時間(默認3s)。
在這段時間內有3個 ping 會發出。如果超時,重新啟動 ping 程式。在網路緩慢時,3秒時間可能不夠,這種情況下,需要慎重增加超時時間,增加超時時間會減慢選舉進程。
一旦節點決定加入一個存在的集群,它會發出一個加入請求給主節點,這個請求的超時時間由discovery.zen.join_time控制,默認是 ping 超時時間(discovery.zen.ping_timeout)的20倍。
當主節點停止或者出現問題,集群中的節點會重新 ping 並選舉一個新節點。有時一個節點也許會錯誤的認為主節點已死,所以這種 ping 操作也可以作為部分網路故障的保護性措施。在這種情況下,節點將只從其他節點監聽有關當前活動主節點的資訊。
discovery.zen.minimum_master_nodes設置了最少有多少個備選主節點參加選舉,同時也設置了一個主節點需要控制最少多少個備選主節點才能繼續保持主節點身份。如果控制的備選主節點少於discovery.zen.minimum_master_nodes的個數,那麼當前主節點下台,重新開始選舉。
為了防止腦裂,通常設置參數為discovery.zen.minimum_master_nodes=N/2+1,其中N為集群中Master節點的個數。建議集群中Master節點的個數為奇數個,如3個或者5個。
2.4、Data Node數據節點
node.data設置為true(默認)的 節點,主要負責集群中數據的索引和檢索,一般壓力比較大。在生產環境中,建議和Master節點分開,避免因為Data Node節點出問題影響到Master節點。創建專用的Data Node節點的參數如下:
node.master: false node.data: true node.ingest: false
2.5、Ingest node預處理節點
node.ingest設置為true(默認)的 節點。Ingest node可以看作是數據前置處理轉換的節點,支援 pipeline管道設置,可以使用 ingest 對數據進行過濾、轉換等操作,類似於 logstash 中 filter的作用,功能相當強大。可以把Ingest節點的功能抽象為:大數據處理環節的「ETL」——抽取、轉換、載入。創建專用的Ingest node節點的參數如下:
node.master: false node.data: false node.ingest: true
2.6、coordinating node協調節點
稱為協調節點或者客戶端節點,當主節點和數據節點配置都設置為false的時候,該節點只能處理路由請求,處理搜索,分發索引操作等,從本質上來說該客戶節點表現為智慧負載平衡器。獨立的客戶端節點在一個比較大的集群中是非常有用的,他協調主節點和數據節點,客戶端節點加入集群可以得到集群的狀態,根據集群的狀態可以直接路由請求。
例如,搜索請求在兩個階段中執行(query 和 fetch),由接收客戶端請求的節點協調:
Ø 在請求階段,協調節點將請求轉發到保存數據的數據節點。每個數據節點在本地執行
請求並將其結果返回給協調節點;
Ø 在收集fetch階段,協調節點將每個數據節點的結果彙集為單個全局結果集。
默認每個節點都是 coordinating 節點,創建專用的協調節點,需要設置其他類型全部為 false,參數設置如下:
node.master: false node.data: false node.ingest: false
2.7、節點類型對比
節點類型 |
作用 |
配置 |
注意事項 |
---|---|---|---|
Master主節點 |
主節點負責輕量級的集群管理,例如: (1)創建和刪除索引; (2)跟蹤哪些節點是集群的一部分; (3)決定要分配給哪些節點的分片。 擁有穩定的主節點對集群監控很重要。 |
node.master: true node.data: false node.ingest: false |
(1)任何具有主控資源的節點(默認都有)都可能被選舉為主節點; (2)候選主節點之間出現了網路分區則可能會出現集群腦裂的情況,導致數據不一致或丟失,可以通過discovery.zen.minimum_master_nodes=N/2+1避免腦裂; |
Data數據節點 |
數據節點保存包含索引文檔的分片: (1)與CRUD、搜索和聚合相關的數據相關操作; (2)這些操作都是I/O、記憶體和CPU密集型; (3)如果監控到這些資源超載,就需要添加更多的數據節點。 |
node.master: false node.data: true node.ingest: false |
|
Ingest預處理節點 |
(1)能執行預處理管道,有自己獨立的任務要執行,類似於logstash的功能,不負責數據和集群相關的事務; (2)能夠再索引之前預處理文檔:攔截文檔的bulk和index請求,轉換,然後再將文檔會給bulk和index api。用戶可以定義一個管道,指定一系列的預處理器。 |
node.master: false node.data: false node.ingest: true search.remote.connect:false |
(1)這個節點的負載會比較大,使用專用的節點作為ingest; (2)建議將主節點和數據節點的node.ingest屬性設置為false。 |
Coordinating協調節點 |
(1)處理路由請求; (2)處理搜索聚合節點; (3)分發批量索引請求。 |
node.master: false node.data: false node.ingest: false search.remote.connect:false |
(1)在大型集群中,建議將協調節點角色從數據節點和具有主控節點分離開來形成一個只協調節點; (2)加入集群並接受全部的集群狀態資訊,跟其他節點一樣,使用集群狀態資訊來路由請求到合適的節點。 |
3、Document 文檔
文檔是構建索引的基本單元。例如,一條客戶數據、一條產品數據、一條訂單數據都可以是一個文檔,文檔以json格式表示。
4、Shard and Replicas 分片和副本
4.1、分片Shard
一個索引可以存儲大量的數據,甚至超出單個節點的磁碟存儲空間。例如,一個索引存儲了數十億文檔,這些文件佔用超過1T的磁碟空間,單台機器無法存儲或者由於太多而無法提供搜索服務。
為了解決這個問題,ES 提供了將單個索引分割成多個分片的功能。創建索引時,可以指定任意數量的分片。每個分片都是一個功能齊全且獨立的「index」,且可以被託管到集群中的任意節點上。分片有兩個重要作用:
1) 它允許您水平拆分/縮放內容量;
2) 它允許您跨分片(可能在多個節點上)分布和並行化操作,從而提高性能/吞吐量。
4.2、副本Replicas
ES 允許為分片生成一個或多個副本,當在發生異常(不管什麼原因導致分片下線或丟失)時有一定的容錯機制。副本有兩個重要作用:
1) 服務高可用:分片異常時,可以通過副本繼續提供服務,因此分片副本不會與主分片分配到同一個節點;
2) 擴展性能:由於查詢操作可以在分片副本上執行,因此可以提升系統的查詢吞吐量。
5、index索引
index是具有某些類似特徵的文檔集合,可以理解為資料庫的database。例如,可以創建店鋪數據的索引,商品的索引以及訂單數據的索引。
索引由名稱標識(必須全部小寫),在對文檔執行索引,搜索,更新和刪除操作時需要引用索引。
6、Type類型
類型,曾經是索引的邏輯類別,允許在同一索引中存儲不同類型的文檔,例如,一種類型用於用戶,另一種類型用於部落格帖子。
注意:官方ES 7.0.0及之後版本將移除映射中的type類型定義,之前版本會繼續支援,詳情請參見官方文檔:https://www.elastic.co/guide/en/elasticsearch/reference/7.3/removal-of-types.html#_what_are_mapping_types
如果在7.0.0及之後版本使用了type,會出現"type": "mapper_parsing_exception"的錯誤提示。
7、Mapping索引映射
在資料庫建表的時候,一般都會指定每個欄位的存儲類型,例如:varchar,int,datetime等等,就是為了更精確的存儲數據,防止數據類型格式混亂。在 Elasticsearch中也是這樣,創建索引的時候一般也需要指定索引的欄位類型、分詞器及屬性等,這種方式成為映射(Mapping),本質上就是index的Scheme。
7.1、欄位數據類型(field datatypes)
每一個欄位,都屬於一種數據類型。資料庫中有varchar,int,datetime等數據類型,ElasticSearch針對每一個欄位,也都有相應的數據類型,具體如下:
1) 核心數據類型
Ø 字元串類型
主要包括:text 和 keyword
Ø 數值類型
主要包括:long, integer, short, byte, double, float, half_float, scaled_float
Ø 日期類型
date
Ø 布爾值類型
boolean
Ø 二進位類型
binary
Ø 範圍類型
integer_range, float_range, long_range, double_range, date_range
text 和 keyword 的區別:
text: 用於索引全文值的欄位,例如,電子郵件正文或產品說明。這些欄位是analyzed,它們通過分詞器傳遞,以在被索引之前將字元串轉換為單個術語的列表。分析過程允許Elasticsearch搜索單個單詞中每個完整的文本欄位。
keyword: 用於索引結構化內容的欄位,例如電子郵件地址,主機名,狀態程式碼,郵政編碼或標籤。它們通常用於過濾,排序,和聚合,keyword欄位只能按其確切值進行搜索。
有時候一個欄位可以同時設置為全文類型(text)和關鍵字類型(keyword):一個用於全文搜索,另一個用於聚合和排序,這可以通過多欄位類型來實現。
2) 複雜數據類型
Ø Array數據類型(Array不需要定義特殊類型)
Ø Object數據類型 (json嵌套)
3) Geo數據類型
Ø 地理數據類型
geo_point 對於緯度/經度點
geo_shape 對於像多邊形這樣的複雜形狀
4) 專用數據類型
Ø ip(IPv4 and IPv6 addresses)
Ø completion(自動完成/搜索)
Ø token_count (數值類型,分析字元串,索引的數量)
Ø murmur3 (索引時計算欄位值的散列並將它們存儲在索引中的功能。 在高基數和大字元串欄位上運行基數聚合時有很大幫助)
Ø join (同一索引的文檔中創建父/子關係)
5) 多欄位
有時候單純的一個欄位類型滿足不了我們複雜的需求,為了不同的目的,可以用不同的方式索引同一個欄位。多欄位也是ES的一種數據類型,只不過結合了更多的功能。
例如,對於字元串欄位,我們既可以將它映射為text類型用於全文搜索,也可以將它映射為keyword類型用於排序或聚合,或者還可以使用標準分詞器、英語分詞器和其他語言分詞器索引文本欄位。
大多數數據類型都通過fields參數支援多欄位。例如,對於城市名稱的多欄位映射,可以這樣寫:
PUT my_index { "mappings": { "_doc": { "properties": { "cityName": { "type": "text", "fields": { "raw": { "type": "keyword" } } } } } } }
以下是常用的參數欄位類型定義&賦值demo:
類型 |
參數定義 |
賦值 |
---|---|---|
text |
"name":{"type":"text"} |
"name": "zhangsan" |
keyword |
"tags":{"type":"keyword"} |
"tags": "abc" |
date |
"date":{"type": "date"} |
"date":"2015-01-01T12:10:30Z" |
long |
"age":{"type":"long"} |
"age" :28 |
double |
"score":{"type":"double"} |
"score":98.8 |
boolean |
"isgirl": { "type": "boolean" } |
"isgirl" :true |
ip |
"ip_addr":{"type":"ip"} |
"ip_addr": "192.168.1.1" |
geo_point |
"location": {"type":"geo_point"} |
"location":{"lat":40.12,"lon":-71.34} |
7.2、索引映射分類:
映射是定義一個文檔及其包含的欄位如何存儲和索引的過程。例如,使用映射來定義:
Ø 應將哪些字元串欄位視為全文欄位。
Ø 哪些欄位包含數字,日期或地理位置。
Ø 是否應將文檔中所有欄位的值索引到catch-all _all欄位中。
Ø 日期值的格式。
Ø 自定義規則以控制動態添加欄位的映射。
其實在 ElasticSearch中可以不需要事先定義映射(Mapping),文檔寫入ElasticSearch時,會根據文檔欄位自動識別類型,但是通過這種自動識別的欄位不是很精確,對於一些複雜的需要分詞的就不適合了。根據是否自動識別映射類型,我們可以將映射分為動態映射和靜態映射。
1) 動態映射 (dynamic mapping):即不需要事先定義映射(Mapping),文檔寫入ElasticSearch時,會根據文檔欄位自動識別類型,這種機制稱之為動態映射。
2) 靜態映射 :動態映射的自動類型推測功能並不能保證100%正確的,這就需要靜態映射。靜態映射與關係資料庫中創建表語句類型,需要事先指定欄位類型。相對於動態映射,靜態映射可以添加更加詳細欄位類型、更精準的配置資訊等。
7.3、映射參數(Mapping parameters)
既然可以自定義映射欄位類型,那麼那些複雜的欄位類型和分詞器我們都可以根據自己需求添加了,以下提供了欄位映射使用的各種映射參數的詳細說明:
mapping parameters |
備註 |
---|---|
analyzer |
指定分詞器,對於text類型的欄位,首先會使用分詞器進行分詞,然後將分詞後的詞根一個一個存儲在倒排索引中,後續查詢主要是針對詞根的搜索。 analyzer該參數可以在查詢、欄位、索引級別中指定,其優先順序如下(越靠前越優先): Ø 欄位上定義的分詞器 Ø 索引配置中定義的分詞器 Ø 默認分詞器(standard) 在查詢上下文,分詞器的查找優先為: Ø full-text query中定義的分詞器 Ø 定義類型映射時欄位中search_an alyzer定義的分詞器 Ø 定義欄位映射時analyzer定義的分詞器 Ø 索引中default_search中定義的分詞器 Ø 索引中默認定義的分詞器 Ø 標準分詞器(standard) |
normalizer |
normalizer 用在索引存儲或者查詢一個keyword類型的欄位之前標準化配置,比如把所有的字元轉化為小寫等 |
boost |
通過指定一個boost值來控制每個查詢子句的相對權重,該值默認為1 |
coerce |
coerce屬性可以用來清除臟數據 |
copy_to |
多欄位的取值被複制到一個欄位並且取值所有欄位的取值組合, 並且可以當成一個單獨的欄位查詢 |
doc_values |
為了加快排序、聚合操作,在建立倒排索引的時候,額外增加一個列式存儲映射,是一個空間換時間的做法。默認是開啟的,對於確定不需要聚合或者排序的欄位可以關閉 |
dynamic |
用於配置新欄位添加時的映射動作,默認情況下,欄位可以自動添加到文檔或者文檔的內部對象,elasticsearc也會自動索引映射欄位 |
enabled |
ELasticseaech默認會索引所有的欄位,enabled設為false的欄位,elasicsearch會跳過欄位內容,該欄位只能從_source中獲取,但是不可搜。而且欄位可以是任意類型。 |
fielddata |
默認情況下,欄位數據在文本欄位上禁用。對需要設置的text型欄位設置fielddata = true,以便通過反轉倒排索引來載入記憶體中的欄位數據。注意,這可以使用大量的記憶體。 |
eager_global_ordinals |
Global ordinals 是一個建立在 doc values 和 fielddata基礎上的數據結構, 它為每一個精確詞按照字母順序維護遞增的編號 |
format |
JSON 文檔內部,日期可能展現為欄位串的樣式. ElasticSearch 內部會將日期數據轉換為UTC |
ignore_above |
超過 ignore_above 的字元串不會被索引 |
ignore_malformed |
如果ignore_malformed參數設為true,異常會被忽略,出異常的欄位不會被索引,其它欄位正常索引 |
index_options |
index_options 參數控制將哪些資訊添加到倒排索引,用於搜索和突出顯示目的 |
index |
index 屬性指定欄位是否索引,不索引也就不可搜索,取值可以為true或者false |
fields |
fields可以讓同一文本有多種不同的索引方式,比如一個String類型的欄位,可以使用text類型做全文檢索,使用keyword類型做聚合和排序。 |
norms |
Norms 存儲各種用於在查詢時計算查詢條件的相關性得分的標準化因子。雖然norms 在計算相關性得分時非常有用, 但是同樣需要消耗大量記憶體 |
null_value |
null_value 屬性可以用指定的值替換空值,用於索引存儲和檢索 |
position_increment_gap |
為了支援短語查詢,需要保存可分詞字元串中分詞的位置 |
properties |
類型映射、對象欄位和嵌套類型欄位包含的子欄位成為屬性。這些屬性可以是任何的數據類型,包括對象和嵌套類型。 properties 在下面這些情況添加: Ø 創建索引的時候明確定義 Ø 利用 PUT mapping API 添加或者修改映射類型時明確定義 Ø 索引新欄位時動態添加 |
search_analyzer |
默認情況下,查詢使用的分析器應該是欄位映射中定義的分析器, 但是我們可以通過search_analyzer 重新設置 |
similarity |
Elasticsearch 允許您為每個欄位配置得分演算法或者相似演算法。similarity 提供了一個簡單的演算法來選擇不同於默認BM25的相似演算法, 例如 TF/IDF |
store |
默認情況下, 欄位取值被索引以便於檢索, 但是不會被存儲,這就意味著欄位可以被檢索但是無法取到原始值。 通常情況下,這並不會有什麼問題,欄位的取值被默認存儲在 _source 欄位中。 如果您只是希望查詢單個欄位或者一些欄位的值而不是整個_source, 您可以通過數據源過濾來實現。 在特定的情況下存儲欄位的值是有意義的。例如,一個文檔具有 a title, a date, and a very large content , 您只是想倒排查詢title 和date 而不是從整個_source檢索。 |
term_vector |
Term vectors 包含分析過程產生的索引詞資訊,包括: Ø 索引詞列表 Ø 每個索引詞的位置(或順序) Ø 索引詞在原始字元串中的原始位置中的開始和結束位置的偏移量。 term vectors 會被存儲,索引它可以作為一個特使的文檔返回。 |
Mapping 欄位設置流程:

7.4、元數據欄位(Meta-Fields)
每個文檔都有與之關聯的元數據,例如_index,_type和_id元欄位。創建映射類型時,可以自定義其中一些元欄位的行為,元數據欄位包括:
1) 身份元數據欄位:
a) _index文檔所屬的索引
b) _type文檔的映射類型,索引的每個文檔都與_type和_id關聯。對該_type欄位進行索引是為了使按名稱快速搜索。
c) _id文檔編號
添加數據時需要添加id來唯一標識文檔。可以自己添加id,如果不添加,系統會自動生成id。
注意:用PUT方法添加文檔時,需要手動指定id,用POST方法時,可以不指定,系統會自動生成id。示例如下:
# Example documents PUT my_index/_doc/1 { "text": "Document with ID 1" } PUT my_index/_doc/2?refresh=true { "text": "Document with ID 2" } GET my_index/_search { "query": { "terms": { "_id": [ "1", "2" ] } } }
2) 文檔源數據元欄位:
a) _source表示文檔正文的原始JSON
b) _size表示插件mapper-size提供的欄位大小(以位元組為單位)
3) 索引元數據欄位:
a) _field_names表示文檔中包含非空值的所有欄位
b) _ignored由於導致索引時間被忽略的文檔中的所有欄位
4) 路由元數據欄位:
a) 自定義的Routing模式
_routing一個自定義的路由值,用於將文檔路由到特定的分片。
使用以下公式將文檔路由到索引中的特定分片:

可以通過為routing 每個文檔指定自定義值來實現自定義路由模式。例如:
PUT my_index/_doc/1?routing=user1&refresh=true { "title": "This is a document" } GET my_index/_doc/1?routing=user1
本文檔使用user1來代替ID路由,在get、delete、update時,需要提供相同的routing值。
這樣使我們的查詢更具目的性。我們不必盲目地去廣播查詢請求,取而代之的是:我們要告訴Elasticsearch我們的數據在哪個分片上。
原來的查詢語句:「請告訴我,USER1的文檔數量一共有多少」
使用自定義Routing(在USESR ID上)後的查詢語句:「請告訴我,USER1的文檔數量一共有多少,它就在第三個分片上,其它的分片就不要去掃描了」。
但是使用 routing的功能,大概率會出現分片大小不均勻的情況,對此 ES 採取的措施是,利用 _id 做二次路由,即相同 value 值,可以進入一個集群(shardList),而不是僅僅一個分片(shard),計算公式如下:

b) 默認用文檔ID路由
Elasticsearch建索引時默認是根據文檔標識符_id 將文檔均分至多個分片,這種演算法基本上會保持所有數據在所有分片上的一個平均分布,而不會產生數據熱點。當搜索數據時,默認查詢所有分片結果然後匯總,而並不必須知道數據到底存在哪個分片上,具體的計算公式如下:

假設有一個100個分片的索引。當一個請求在集群上執行時會發生什麼呢?
Ø 這個搜索的請求會被發送到一個節點;
Ø 接收到這個請求的節點,將這個查詢廣播到這個索引的每個分片上(可能是主分片,也可能是副本分片);
Ø 每個分片執行這個搜索查詢並返回結果;
Ø 結果在通道節點上合併、排序並返回給用戶。
因為默認情況下,Elasticsearch使用文檔的ID(類似於關係資料庫中的自增ID,當然,如果不指定ID的話,Elasticsearch使用的是隨機值)將文檔平均的分布於所有的分片上,這導致了Elasticsearch不能確定文檔的位置,所以它必須將這個請求廣播到所有的100個分片上去執行。這同時也解釋了為什麼主分片的數量在索引創建的時候是固定下來的,並且永遠不能改變。因為如果分片的數量改變了,所有先前的路由值就會變成非法了,文檔相當於丟失了。
5) 其他元數據欄位:
_meta特定於應用程式的元數據。