Elasticsearch7.1中文文檔-第五章-文檔API

本節首先簡要介紹Elasticsearch的數據複製模型,而後會對CRUD API進行詳細說明:html

單文檔API
多文檔API

全部CRUD API都是單索引API。 index參數接受單個索引名稱或指向單個索引的aliasnode

讀寫文檔

介紹

在Elasticsearch中,每一個索引都會被分紅分片,每一個分片會有多個副本分片。這些副本稱爲複製組(replication group),在添加或刪除文檔時會保持同步。若是咱們同步,從一個副本中讀取將致使與從另外一個副本中讀取的結果大相徑庭的結果。保持副本同步和讀取數據提供服務的過程稱爲數據複製模型。web

Elasticsearch的是數據複製模型是基於主從模型的,並在微軟研究院的PacificA論文中有更好的描述。主分片是從複製組中複製的一個副本。其餘副本則被稱爲副本分片。主節點是全部索引操做的主要入口點,它負責驗證它們並確保它們是正確的。一旦索引操做被主節點接受,主節點還負責將該操做複製到其餘副本。shell

本節的目的是對Elasticsearch複製模型進行更深的概述,並討論它對寫操做和讀操做之間的各類交互的影響。數據庫

基礎的寫模型

Elasticsearch中的每一個索引操做首先使用路由(一般基於文檔ID)解析到一個複製組。一旦肯定了複製組,操做將在內部轉發到該組的當前主分片。主分片負責驗證操做並將其轉發到其餘副本。因爲副本能夠脫機,因此不須要主分片複製到全部副本。相反,Elasticsearch維護一個應該接收操做的分片副本列表。這個列表稱爲同步副本,由主節點維護,所以必須將全部操做複製到這個副本列表中的每一個副本。顧名思義,分片副本保證已經處理了全部已向用戶確認的索引和刪除操做。編程

主分片遵循如下基本流程:json

  1. 驗證傳入操做並在結構無效時拒絕它,換言之,須要傳入符合結構的參數(例如:在須要一個數字的對象字段中)
  2. 在本地執行操做,即索引或刪除相關文檔。這還將驗證字段的內容,不符要求會拒絕(例如:關鍵字值太長,沒法在Lucene中進行索引)。
  3. 將操做轉發到當前同步複製集中的每一個副本,若是有多個副本,則並行執行。
  4. 一旦全部副本都成功地執行了操做並響應了主副本,主副本就會向客戶端確認請求成功完成。
失敗處理

在索引期間有不少事情能夠致使出錯——磁盤可能會損壞,節點可能會相互斷開鏈接,或者某些配置錯誤可能致使副本上的操做失敗,儘管它在主服務器上成功。 這些不多見,但主要必須迴應它們。api

在主節點自己發生故障的狀況下,託管主節點的節點將向主請求發送有關它的消息。 索引操做將等待(默認狀況下最多1分鐘),主節點將其中一個副本提高爲新的主節點。 而後,該操做將被轉發到新的主節點處理。 請注意,主節點還會監控節點的運行情況,並可能決定主動降級主節點。 當經過網絡問題將擁有主節點的節點與羣集隔離時,一般會發生這種狀況。 有關詳細信息,請參見此處數組

一旦在主節點上成功執行了操做,在副本分片上執行該操做時,主節點必須處理潛在的問題。 這多是由副本上的實際故障或因爲網絡問題致使操做沒法到達副本(或阻止副本響應)引發的。 全部這些都具備相同的最終結果:做爲同步副本列表的一部分的副本錯過了即將被確認的操做。 爲了不違反規則,主節點向主請求發送消息,請求從同步副本列表中刪除有問題的分片。 只有在主請求確認刪除了分片後,主請求才會確認操做。 請注意,主節點還將指示另外一個節點開始構建新的分片副本,以便將系統恢復到正常狀態。安全

在將操做轉發到副本時,主節點將使用副原本驗證它仍然是活動的主節點。若是主節點因爲網絡分區(或長時間GC)而被隔離,它可能會在乎識到已降級以前繼續處理傳入索引操做。來自舊主節點的操做將被副本拒絕。當主節點收到來自副本的響應,拒絕了它的請求(由於它再也不是主節點),那麼主節點就會向主服務器發出請求,並知道它已經被替換了。而後將操做路由到新的主節點。

若是沒有副本會發生什麼?

咱們只使用數據的單一副本運行,物理硬件問題可能會致使數據丟失。

基礎的讀模型

Elasticsearch中的讀取能夠是ID很是輕量級的查找,也能夠是具備複雜聚合的大量搜索請求,這些聚合會佔用很是珍貴的CPU能力。 主從模型的一個優勢是它使全部分片副本保持一致(除了正在進行的操做)。 所以,單個同步副本足以提供讀取請求。

當節點接收到讀請求時,該節點負責將其轉發給包含相關分片的節點、整理並響應客戶端。咱們將該節點稱爲請求的協調節點。基本流程以下:

  1. 將讀請求解析到相關分片。注意,因爲大多數搜索將被髮送到一個或多個索引,所以它們一般須要從多個分片中讀取,每一個分片表示數據的不一樣子集。
  2. 從分片複製組中選擇每一個相關分片的活動副本。這能夠是主分片的,也能夠是副本。默認狀況下,Elasticsearch只是在分片副本之間進行循環。
  3. 將分片級別的讀請求發送到所選副本。
  4. 整合結果並作出響應。注意,在經過ID查找的狀況下,必定是隻有一個結果,能夠跳過這一步。
(請求)分片失敗

當分片沒法響應讀請求時,協調節點將請求發送到相同複製組中的另外一個分片副本。重複失敗會致使沒有可用的分片副本。

爲了確保快速響應,若是一個或多個分片失敗,如下api將響應部分結果:

包含部分結果的響應仍然提供一個200 OK HTTP狀態碼。分片故障由響應頭的timed_out_shards字段表示。

一些簡單的含義

這些基本流程中的每個都決定了Elasticsearch做爲讀寫系統的行爲。此外,因爲讀寫請求能夠併發執行,因此這兩個基本流彼此交互。這有一些固有的含義:

高效讀

在正常操做下,對每一個相關複製組執行一次讀取操做。 只有在失敗條件下,同一個分片的多個副本纔會執行相同的搜索。

讀未應答

因爲主節點的第一個索引在本地而後複製請求,所以併發讀取可能在確認以前已經看到了更改。

因爲主節點的第一個索引是本地索引,而後複製請求,因此併發讀取可能在確認更改以前就已經看到了更改。

默認兩個分片

這樣能夠提升容錯,同時保留兩個數據副本。

失敗

如下狀況可能致使失敗:

單個分片能夠下降索引速度

因爲主節點在每次操做期間都要等待同步副本列表中的全部副本,所以一個慢速副本可能會減慢整個複製組的速度。這是咱們爲上面提到的讀取效率所付出的代價。固然,一個單一的慢分片也會減慢已經被路由到它的搜索。

髒讀

一個獨立的主節點暴露寫入,寫入是不會確認的。這是由於獨立主節點只有在向其副本發送請求或向主節點發出請求時纔會意識到它是隔離的。此時,操做已經被索引到主節點中,而且能夠併發讀取。Elasticsearch每秒鐘(默認狀況下)ping一次主節點,若是不知道主節點,則拒絕索引操做,從而下降了這種風險。

冰山一角

本文檔提供了更高級的Elasticsearch如何處理數據的預覽,固然,表面之下ES作了不少事情。好比,集羣狀態發佈,主節點選舉等在保證系統正常運行方面發揮了不小的做用。這個文檔沒有涵蓋已知的和重要的bug(關閉的和打開的),爲了幫助人們知道並瞭解,咱們在咱們的網站上保持一個專門的頁面。咱們強烈建議閱讀它。

Index API

添加或更新JSON文檔到指定索引,使該文檔可搜索,下面的例子演示了插入一個文檔到JSON文檔到twitter索引中,而且id爲1:

curl -X PUT "localhost:9200/twitter/_doc/1" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼

上面索引的操做結果是:

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    },
    "_index" : "twitter",
    "_type" : "_doc",
    "_id" : "1",
    "_version" : 1,
    "_seq_no" : 0,
    "_primary_term" : 1,
    "result" : "created"
}
複製代碼

_shard提供了關於索引操做的複製過程的信息。

total表示多少分片須要被執行該索引操做(包含主分片和副本分片)。

successful表示全部分片中有多少成功的。

failed表示有多少分片是執行失敗的。

若是索引操做成功,則successful至少爲1。

當一個索引操做返回成功(默認狀況下,只有主分片是必須的,可是此行爲是能夠改變的 ),副本分片可能沒有所有開始。在上面的例子中,total將等於number_of_replicas設置的總分片數,successful將等於已開始的執行的分片數(主+副),若是沒有失敗,則failed是0.

自動建立索引

若是索引不存在,建立索引操做將會建立一個索引,並應用預配置index模板。若是映射不存在,建立索引操做還會動態建立索引。默認的,若是須要,新字段和對象將會自動的添加到映射定義。有關映射定義的更多信息,請查看映射部分;有關手動更新映射的信息,請參閱Put Mapping API

自動建立索引是經過action.auto_create_index設置來控制的,這個設置默認是true,意味着索引老是會自動建立。只有匹配特定模式的索引才容許自動建立索引,方法是將此設置的值更改成這些模式的逗號分隔列表。還能夠明確的在列表中使用+或者-來指定容許或者禁止,要完全的禁用能夠將其設置爲false

curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
    "persistent": {
    	##只容許自動建立twitter,index10或者以ind開頭的索引,禁止建立以index1開頭的索引
        "action.auto_create_index": "twitter,index10,-index1*,+ind*" 
    }
}
'
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
    "persistent": {
    	##徹底禁用自動建立索引
        "action.auto_create_index": "false" 
    }
}
'
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
    "persistent": {
    	##容許自動建立全部索引
        "action.auto_create_index": "true" 
    }
}
'
複製代碼
操做類型

索引操做還接受op_type參數,用於強制create操做,容許省略。當使用了create,在索引中若是索引中已存在該ID的文檔,索引操做將失敗。

下面有一個例子使用了op_type參數:

curl -X PUT "localhost:9200/twitter/_doc/1?op_type=create" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼

指定選項爲create使用下面的URI:

curl -X PUT "localhost:9200/twitter/_create/1" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼
自動生成ID

索引操做沒有指定id也能夠被執行,下面的例子ID將會自動生成。此外,op_type將會自動的被設置爲create,請看下面的例子(注意,是POST而不是PUT):

curl -X POST "localhost:9200/twitter/_doc/" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼

上面索引操做的結果是:

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    },
    "_index" : "twitter",
    "_type" : "_doc",
    "_id" : "W0tpsmIBdwcYyG50zbta",
    "_version" : 1,
    "_seq_no" : 0,
    "_primary_term" : 1,
    "result": "created"
}
複製代碼
樂觀併發控制

索引操做能夠是有條件的,只有在爲文檔的最後一次修改分配了if_seq_noif_primary_term參數指定的序列號和主要術語時才能執行索引操做。 若是檢測到不匹配,則操做將致使VersionConflictException和狀態代碼409.有關詳細信息,請參閱樂觀併發控制

路由

默認狀況下,分片放置? 仍是路由? 經過使用文檔的id值的哈希來控制。 爲了更明確地控制,可使用路由參數在每一個操做的基礎上直接指定饋入路由器使用的散列函數的值。 例如:

curl -X POST "localhost:9200/twitter/_doc?routing=kimchy" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼

在上面的例子中,_doc文檔是被路由到routing提供的參數「kimchy」中,當明確的設置映射,__route字段用來直接的索引操做從自身文檔中來提取路由值,這是以額外的文檔解析傳遞(很是小)的代價實現的。若是routing映射被定義,而且設置爲required,若是沒有路由值提供或者能夠提取,這個索引操做將失敗。

分發

索引操做根據其路由指向主分片,並在包含此分片的實際節點上執行。主分片完成操做後,若是須要,更新將分發到可應用的副本。

等待活動分片

爲了提升系統寫入的容錯性,索引操做能夠配置爲在繼續操做以前等待必定數量的活動分片副本。若是必要數量的活動分片副本不可用,則寫入操做必須等待並重試,直到必要的分片副本已啓動或發生超時。默認的,寫入操做在處理以前,會等待主分片啓動(例如:wait_for_active_shards=1)。這個默認值能夠經過index.write.wait_for_active_shards來動態的修改此設置。要更改每一個操做的此行爲,可使用wait_for_active_shards請求參數。

有效值能夠是all也能夠是在索引中配置副本節點的每一個分片的總數的任意正整數(即number_of_replicas + 1),指定負數,或者大於該分片副本數的值將引起錯誤。

例如,假設咱們有三個節點造成的集羣,A,B和C,建立一個索引index副本數量設置爲3(產生4個分片副本,比節點多一個副本)。若是咱們嘗試一個索引操做,默認的在處理以前,操做只會確保每一個分片的主副本可用。這意味着,即便B和C掛掉了,A託管了主分片副本,索引操做仍將僅使用一個數據副本。 若是wait_for_active_shards被該請求設置爲3(和全部3個節點是正常的),索引操做在處理以前將須要3個活動分片副本,應該知足這個需求,由於集羣中有3個活動節點,每一個節點都持有切分的副本。可是,若是咱們將wait_for_active_shards設置爲all(或者設置爲4,二者是同樣的),索引操做將不會進行,由於索引中咱們並無每一個活動分片的4個副本。除非集羣中出現一個新節點來承載分片的第四個副本,不然操做將超時。

須要注意的是,這個設置極大地下降了寫操做未寫入到所需分片副本數量的機會,但它並無徹底消除這種可能性,由於這個檢查發生在寫操做開始以前。在執行寫操做以後,仍然有可能在任意數量的碎片副本上覆制失敗,但在主副本上仍然成功。寫操做的響應的_shards部分顯示覆製成功/失敗的shard副本的數量。

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    }
}
複製代碼
刷新

控制什麼時候能夠搜索到此請求所作的更改。詳情請查看刷新

Noop更新

當使用索引API更新文檔時,即便文檔沒有更改,也老是會建立文檔的新版本。若是您不能接受這種結果,請使用_update API,並將detect_noop設置爲true。此選項在索引API上不可用,由於索引API不會獲取舊源,也沒法將其與新源進行比較。

關於什麼時候不接受noop更新,沒有一條硬性規定。 它是許多因素的組合,例如您的數據源發送實際noops更新的頻率以及Elasticsearch在接收更新的分片上運行的每秒查詢數。

超時

在執行索引操做時,分配給執行索引操做的主分片可能不可用。其中的一些緣由多是主分片目前正在從網關中恢復或正在進行從新定位。默認狀況下,索引操做將等待主分片可用最多1分鐘,而後失敗並響應錯誤。可使用timeout參數顯式地指定它等待的時間。下面是一個設置爲5分鐘的例子:

curl -X PUT "localhost:9200/twitter/_doc/1?timeout=5m" -H 'Content-Type: application/json' -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'
複製代碼
版本控制

每一個索引文檔都有一個版本號,默認的,每一次更新或者刪除內部版本使用從1自增的數字,固然也可使用一個外部的值(例如,維護在數據庫中的版本號),要啓用這個功能,設置version_typeexternal,這個值必須是一個數字,大於或等於0,小於9.2e+18。

當使用外部的版本類型,系統將檢查傳遞給索引請求的版本號是否大於當前存儲文檔的版本,若是是大於,則文檔將被索引,而且生成一個新的版本號來使用。若是提供的值是小於或者等於存儲的文檔版本號,會發生版本衝突,而且索引操做將失敗,例如:

curl -X PUT "localhost:9200/twitter/_doc/1?version=2&version_type=external" -H 'Content-Type: application/json' -d'
{
    "message" : "elasticsearch now has versioning support, double cool!"
}
'
複製代碼

版本控制是徹底實時的,而且不受搜索操做的近實時方面的影響。若是沒有提供版本,接下來的執行操做不會進行版本檢查。

上面的操做時成功的,由於提供了版本號爲2,並大於當前的版本號1,若是文檔已經被更新,版本號設置爲2或者更高,索引命令將失敗並致使衝突(409 http狀態碼)。

一個很好的反作用是,只要使用源數據庫的版本號,就不須要維護因爲更改源數據庫而執行的異步索引操做的嚴格順序。若是使用外部版本控制,即便使用來自數據庫的數據更新Elasticsearch索引的簡單狀況也會簡化,由於若是索引操做因爲某種緣由出現順序錯誤,則只使用最新版本。

版本類型

除了上面解釋的external版本類型以外,Elasticsearch還支持針對特定用例的其餘類型。下面是不一樣版本類型及其語義的概述。

internal

​ 只有當給定的版本與存儲的文檔版本相同時,才索引文檔。

external or external_gt

​ 只有當給定的版本嚴格高於存儲文檔的版本,或者沒有現有文檔時,纔對文檔進行索引。給定的版本將做爲新版本使用,並與新文檔一塊兒存儲。所提供的版本必須是非負的long number。

external_gte

​ 只有當給定的版本等於或高於存儲文檔的版本時,纔對文檔進行索引。若是沒有現有文檔,操做也將成功。給定的版本將做爲新版本使用,並與新文檔一塊兒存儲。所提供的版本必須是非負的long number。

external_gte版本類型用於特殊的用例,應該謹慎使用。若是使用不當,可能會致使數據丟失。還有另外一個選項force,它是不推薦的,由於它可能致使主f分片和複製分片出現不一致。

GET API

get API容許根據索引的id從索引中獲取JSON文檔。下面的例子展現了從一個索引叫作twitter的而且id等於0的索引中獲取JSON文檔。

curl -X GET "localhost:9200/twitter/_doc/0"
複製代碼

上面的get操做結果是:

{
    "_index" : "twitter",
    "_type" : "_doc",
    "_id" : "0",
    "_version" : 1,
    "_seq_no" : 10,
    "_primary_term" : 1,
    "found": true,
    "_source" : {
        "user" : "kimchy",
        "date" : "2009-11-15T14:12:12",
        "likes": 0,
        "message" : "trying out Elasticsearch"
    }
}
複製代碼

上面的結果包括咱們但願檢索的文檔的index、id和version,若是能夠找到文檔的實際_source,則包含它(如響應中的found字段所示)。

該API還可使用head請求來檢查文檔是否存在,例如:

curl -I "localhost:9200/twitter/_doc/0"
複製代碼
實時

默認的,get API是實時的,它不受index的刷新率影響(當數據在搜索中可見時),若是文檔已經更新完成但尚未刷新,get API將發出一個刷新調用,使文檔可見,這也將使上次刷新後其餘文檔發生變化。爲了禁用實時GET,能夠將realtime參數設置爲false

Source過濾

默認狀況下,get操做會返回_source字段的內容,除非你使用了stroed_fields參數或者_source字段是被禁用的。你可使用_source參數來關閉_source檢索。

curl -X GET "localhost:9200/twitter/_doc/0?_source=false"
複製代碼

若是你只須要從完整的_source中的一個或者兩個字段,您可使用_source_include_source_exclude參數來包含或過濾掉您須要的部分。這對於部分檢索能夠節省網絡開銷的大型文檔尤爲有用。這兩個參數都採用逗號分隔的字段列表或通配符表達式。例如:

curl -X GET "localhost:9200/twitter/_doc/0?_source_includes=*.id&_source_excludes=entities"
複製代碼

若是你只指定包含,你可使用一個更短的符號:

curl -X GET "localhost:9200/twitter/_doc/0?_source=*.id,retweeted"
複製代碼
存儲字段

get操做容許指定一組存儲字段,這些字段將經過傳遞stored_fields參數返回。若是未存儲所請求的字段,則將忽略它們。例如:

curl -X PUT "localhost:9200/twitter" -H 'Content-Type: application/json' -d'
{
   "mappings": {
       "properties": {
          "counter": {
             "type": "integer",
             "store": false
          },
          "tags": {
             "type": "keyword",
             "store": true
          }
       }
   }
}
'
複製代碼

如今沒問能夠添加一個文檔:

curl -X PUT "localhost:9200/twitter/_doc/1" -H 'Content-Type: application/json' -d'
{
    "counter" : 1,
    "tags" : ["red"]
}
'
複製代碼

接下來嘗試檢索它:

curl -X GET "localhost:9200/twitter/_doc/1?stored_fields=tags,counter"
複製代碼

上面的結果是:

{
   "_index": "twitter",
   "_type": "_doc",
   "_id": "1",
   "_version": 1,
   "_seq_no" : 22,
   "_primary_term" : 1,
   "found": true,
   "fields": {
      "tags": [
         "red"
      ]
   }
}
複製代碼

從文檔自己獲取的字段值老是做爲數組返回。因爲未存儲counter字段,所以在嘗試獲取stored_field時,get請求會忽略它。

也能夠檢索像_routing字段這樣的元數據字段:

curl -X PUT "localhost:9200/twitter/_doc/2?routing=user1" -H 'Content-Type: application/json' -d'
{
    "counter" : 1,
    "tags" : ["white"]
}
'
複製代碼
curl -X GET "localhost:9200/twitter/_doc/2?routing=user1&stored_fields=tags,counter"
複製代碼

上面的操做結果是:

{
   "_index": "twitter",
   "_type": "_doc",
   "_id": "2",
   "_version": 1,
   "_seq_no" : 13,
   "_primary_term" : 1,
   "_routing": "user1",
   "found": true,
   "fields": {
      "tags": [
         "white"
      ]
   }
}
複製代碼

此外,只能經過stored_field選項返回leaf字段。 所以沒法返回對象字段,此類請求將失敗。

直接獲取_source

使用/ {index} / _ source / {id}只獲取文檔的_source字段,而不包含任何其餘內容。 例如:

curl -X GET "localhost:9200/twitter/_source/1"
複製代碼

你還可使用source過濾參數來控制哪些_source部分將會被返回:

curl -X GET "localhost:9200/twitter/_source/1/?_source_includes=*.id&_source_excludes=entities"
複製代碼

注意,_source還有一個HEAD變量,用於有效地測試文檔_source是否存在。若是在映射中禁用現有文檔的_source,則該文檔將沒有_source。

curl -I "localhost:9200/twitter/_source/1"
複製代碼
路由

使用控制路由的能力進行索引時,爲了獲取文檔,還應提供路由值。 例如:

curl -X GET "localhost:9200/twitter/_doc/2?routing=user1"
複製代碼

上面的將得到id爲2的tweet,根據用戶路由。注意,在沒有正確路由的狀況下發出get將致使沒法獲取文檔。

偏好

控制哪一個分片副本執行get請求的偏好。默認狀況下,操做是在分片副本間是隨機的。

preference 能被設置成如下值:

_local

​ 若是可能,該操做更喜歡在本地分配的分片上執行。

自定義值

​ 將使用自定義值來保證相同的分片將用於相同的自定義值。 當在不一樣的刷新狀態下命中不一樣的分片時,這能夠幫助「jumping values」。 示例值能夠是Web會話ID或用戶名。

刷新

能夠將refresh參數設置爲true,以便在get操做以前刷新相關分片並使其可搜索。將其設置爲true應該在仔細考慮並驗證這不會給系統帶來沉重的負載(並下降索引速度)以後執行。

分佈式

get操做被散列到一個特定的shard id中,而後被重定向到該shard id中的一個副本,並返回結果。副本是主分片及其在該shard id組中的副本。

版本支持

只有當文檔的當前版本等於指定的版本時,纔可使用version參數檢索文檔。這種行爲對於全部版本類型都是相同的,除了老是檢索文檔的版本類型FORCE以外。注意,不推薦使用FORCE版本類型。

在內部,Elasticsearch將舊文檔標記爲已刪除,並添加了一個全新的文檔。舊版本的文檔不會當即消失,儘管您沒法訪問它。當您繼續索引更多數據時,Elasticsearch將清理後臺已刪除的文檔。

Delete API

delete API容許從指定的索引中用索引id刪除JSON文檔。下面的例子展現了刪除一個json文檔從索引叫作twitter而且ID爲1:

curl -X DELETE "localhost:9200/twitter/_doc/1"
複製代碼

上面的操做結果是:

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    },
    "_index" : "twitter",
    "_type" : "_doc",
    "_id" : "1",
    "_version" : 2,
    "_primary_term": 1,
    "_seq_no": 5,
    "result": "deleted"
}
複製代碼
樂觀併發控制

刪除操做能夠是有條件的,只有在爲文檔的最後一次修改分配了if_seq_noif_primary_term參數指定的序列號和主要術語時才能執行。 若是檢測到不匹配,則操做將致使VersionConflictException和狀態代碼409.有關詳細信息,請參閱樂觀併發控制

版本控制

索引的每一個文檔都是版本化的。 刪除文檔時,能夠指定版本以確保咱們嘗試刪除的相關文檔實際上已被刪除,而且在此期間沒有更改。 對文檔執行的每一個寫入操做(包括刪除)都會致使其版本遞增。 刪除文檔的版本號在刪除後仍可短期使用,以便控制併發操做。 已刪除文檔的版本保持可用的時間長度由index.gc_deletes索引設置肯定,默認爲60秒。

路由

當索引使用控制路由的能力時,爲了刪除文檔,還應該提供路由值。例如:

curl -X DELETE "localhost:9200/twitter/_doc/1?routing=kimchy"
複製代碼

以上將刪除id爲1的tweet ,根據用戶進行路由。 請注意,在沒有正確路由的狀況下發出刪除將致使文檔不被刪除。

_routing映射根據須要設置且未指定路由值時,delete API將拋出RoutingMissingException並拒絕該請求。

自動建立索引

若是使用外部版本控制變體(variant),則刪除操做會自動建立索引(若是以前還沒有建立)(請查看create index API以手動建立索引)。

分佈式

刪除操做將散列爲特定的分片ID。 而後它被重定向到該id組中的主分片,並複製(若是須要)到該id組內的分片副本。

等待活動分片

在發出刪除請求時,能夠設置wait_for_active_shards參數,以要求在開始處理刪除請求以前激活最少數量的分片副本。有關詳細信息和使用示例,請參見此處

刷新

控制什麼時候能夠搜索到此請求所作的更改。詳情參見?refresh

超時

執行刪除操做時,分配用於執行刪除操做的主分片可能不可用。 形成這種狀況的一些緣由多是主分片當前正在從倉庫恢復或正在進行重定位。 默認狀況下,刪除操做將在主分片上等待最多1分鐘,而後失敗並響應錯誤。 timeout參數可用於顯式指定等待的時間。 如下是將其設置爲5分鐘的示例:

curl -X DELETE "localhost:9200/twitter/_doc/1?timeout=5m"
複製代碼

經過Query API來刪除

_delete_by_query的最簡單用法是對查詢匹配到的文檔執行刪除操做。這是API:

curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d'
{
 #查詢必須傳遞一個值給`query`,方法與SearchAPI相同,你也可使用q參數。
  "query": { 
    "match": {
      "message": "some message"
    }
  }
}
'
複製代碼

響應結果爲:

{
  "took" : 147,
  "timed_out": false,
  "deleted": 119,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "total": 119,
  "failures" : [ ]
}
複製代碼

_delete_by_query啓動並刪除使用內部版本控制找到的內容時,它會獲得一個索引的快照,這意味着,若是在捕獲快照和處理刪除請求之間的文檔發生更改,您將會獲得版本衝突。只有文檔匹配的時候,纔會刪除文檔。

由於``internal版本控制不支持0做爲有效版本號,版本等於0的文檔不能使用_delete_by_query來刪除,而且請求會失敗。

在執行_delete_by_query期間,多個搜索請求依次執行,以便找到全部要刪除的匹配文檔。每次找到一批文檔時,都會執行相應的批量請求來刪除這些文檔。方式搜索或者刪除被拒絕,_delete_by_query依賴一個默認策略來重試被拒絕的請求(最多10次)。到達最大的重試限制,將致使_delete_by_query終止,失敗信息將在響應中返回。已經執行的操做仍然保持不變。換言之,這個過程是不可逆的,只能終止。在第一次失敗致使終止,失敗的批量請求返回的全部故障都在failure元素中返回,所以,有可能存在至關多的失敗實體。

若是你想計算版本衝突,而不是終止緣由,能夠在url中設置conflicts=proceed或者在請求體中添加"conflicts": "proceed"

回到API格式,這將從twitter索引中刪除tweet:

curl -X POST "localhost:9200/twitter/_delete_by_query?conflicts=proceed" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'
複製代碼

也能夠同時刪除多個索引的文檔,就像搜索API:

curl -X POST "localhost:9200/twitter,blog/_delete_by_query" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match_all": {}
  }
}
'
複製代碼

若是提供路由,則將路由複製到滾動查詢,將處理過程分配給匹配該路由值的分片:

curl -X POST "localhost:9200/twitter/_delete_by_query?routing=1" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range" : {
        "age" : {
           "gte" : 10
        }
    }
  }
}
'
複製代碼

默認狀況下,_delete_by_query使用1000的滾動批次。您可使用scroll_size URL參數更改批量大小:

curl -X POST "localhost:9200/twitter/_delete_by_query?scroll_size=5000" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
'
複製代碼
URL參數

除了像pretty這樣的標準參數以外,查詢API的刪除還支持refreshwait_for_completionwait_for_active_shardstimeoutscroll

發送refresh將在請求完成後刷新查詢刪除中涉及的全部分片。 這與delete API的refresh參數不一樣,後者只會刷新收到刪除請求的分片。 與delete API不一樣,它不支持wait_for

若是請求包含wait_for_completion = false,則Elasticsearch將執行一些預檢查,啓動請求,而後返回可與Tasks API一塊兒使用的任務,以取消或獲取任務的狀態。 Elasticsearch還將在.tasks / task / $ {taskId}中建立此任務的記錄做爲文檔。 這是你的保留或刪除你認爲合適的。 完成後將會刪除它,以便Elasticsearch能夠回收它使用的空間。

wait_for_active_shards控制在繼續請求以前必須激活分片的副本數。 timeout指示每一個寫入請求等待不可用分片可用的時間。 二者都徹底適用於Bulk API中的工做方式。 因爲_delete_by_query使用滾動搜索,您還能夠指定scroll參數來控制search context保持活動的時間,例如?scroll=10m。 默認狀況下,它是5分鐘。

requests_per_second能夠設置爲任何正十進制數(1.4,6,1000等),並經過在等待時間內填充每一個批次來限制查詢刪除發出批量刪除操做的速率。 能夠經過將requests_per_second設置爲-1來禁用限制。

節流是經過在批之間等待來完成的,這樣就能夠給_delete_by_query內部使用的滾動設置一個考慮填充的超時。填充時間是批大小除以requests_per_second和寫入時間之間的差額。默認狀況下批處理大小爲1000,因此若是requests_per_second被設置爲500:

target_time = 1000 / 500 per second = 2 seconds
wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds
複製代碼

因爲批處理是做爲單個_bulk請求發出的,所以較大的批處理將致使Elasticsearch建立許多請求,而後等待一段時間再啓動下一個請求集。這是突發的而不是平滑的。默認值是-1。

響應體
{
  "took" : 147,
  "timed_out": false,
  "total": 119,
  "deleted": 119,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "failures" : [ ]
}
複製代碼

took

​ 整個操做從開始到結束的毫秒數。

time_out

​ 若是在delete by query執行期間執行的任何請求超時,則將此標誌設置爲true。

total

​ 成功執行的文檔總數

deleted

​ 成功刪除的文檔總數

batches

​ 經過查詢刪除回滾的滾動響應數。

version_conflicts

​ 按查詢刪除所命中的版本衝突數。

noops

​ 對於delete by query,這個字段老是等於零。它的存在只是爲了讓delete by query、update by query和reindex api返回具備相同結構的響應。

retries

​ 按查詢刪除所嘗試的重試次數。bulk是重試的批量操做的數量,search是重試的搜索操做的數量。

throttled_millis

​ 符合requests_per_second的請求毫秒數

requests_per_second

​ 在delete by query期間每秒有效執行的請求數。

throttled_until_millis

​ 在_delete_by_query響應中,此字段應始終等於零。 它只在使用Task API時有意義,它表示下一次(自epoch以來的毫秒數),爲了符合requests_per_second,將再次執行受限制的請求。

failures

​ 若是流程中存在任何不可恢復的錯誤,則會出現一系列故障。若是這不是空的,那麼請求就會由於這些失敗而停止。使用batch實現Delete by query,任何失敗都會致使整個進程停止,可是當前batch中的全部失敗都會收集到數組中。您可使用conflicts選項來防止reindex在版本衝突上停止。

使用Task API

你可使用Task API來獲取運行delete by query請求的狀態:

curl -X GET "localhost:9200/_tasks?detailed=true&actions=*/delete/byquery"
複製代碼

響應結果:

{
  "nodes" : {
    "r1A2WoRbTwKZ516z6NEs5A" : {
      "name" : "r1A2WoR",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "attributes" : {
        "testattr" : "test",
        "portsfile" : "true"
      },
      "tasks" : {
        "r1A2WoRbTwKZ516z6NEs5A:36619" : {
          "node" : "r1A2WoRbTwKZ516z6NEs5A",
          "id" : 36619,
          "type" : "transport",
          "action" : "indices:data/write/delete/byquery",
          "status" : {    
            "total" : 6154,
            "updated" : 0,
            "created" : 0,
            "deleted" : 3500,
            "batches" : 36,
            "version_conflicts" : 0,
            "noops" : 0,
            "retries": 0,
            "throttled_millis": 0
          },
          "description" : ""
        }
      }
    }
  }
}
複製代碼

該對象包含實際狀態。 它就像響應JSON同樣,增長了total 字段。 totalreindex指望執行的操做總數。 您能夠經過添加updatedcreateddeleted的字段來估計進度。 當它們的總和等於total字段時,請求將結束。

經過Task id能夠直接查看Task:

curl -X GET "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619"
複製代碼

此API的優勢是它與wait_for_completion = false集成,透明地返回已完成任務的狀態。 若是任務完成而且在其上設置了wait_for_completion = false,那麼它將返回resulterror 字段。 此功能的代價是wait_for_completion = false.tasks / task / $ {taskId}建立的文檔。 您能夠刪除該文檔。

使用Cancel Tash API

全部的delete by query能經過task cancel API被關閉:

curl -X POST "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel"
複製代碼

Task ID能夠經過task API來找到。

取消操做應該快速的發生,可是有時可能會幾秒。上面的任務狀態API將繼續按查詢任務列出delete,直到該任務檢查它是否已被取消並自行終止。

Rethrottling

可使用_rethrottle API經過查詢在正在運行的刪除時更改requests_per_second的值:

curl -X POST "localhost:9200/_delete_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1"
複製代碼

經過Task id能夠直接查看Task.

就像在查詢API的刪除中設置它同樣,requests_per_second能夠是-1來禁用限制,也能夠是1.7或12之類的任何十進制數來限制到該級別。 加速查詢的Rethrottling會當即生效,但從新啓動會減慢查詢速度,這將在完成當前批處理後生效。 這能夠防止滾動超時。

切分請求

按查詢刪除支持分割滾動以並行化刪除過程。 這種並行化能夠提升效率,並提供一種方便的方法將請求分解爲更小的部分。

手動切分

經過對每一個請求提供一個切分id和切分的總數來手動的切分delete by query

curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d'
{
  "slice": {
    "id": 0,
    "max": 2
  },
  "query": {
    "range": {
      "likes": {
        "lt": 10
      }
    }
  }
}
'
curl -X POST "localhost:9200/twitter/_delete_by_query" -H 'Content-Type: application/json' -d'
{
  "slice": {
    "id": 1,
    "max": 2
  },
  "query": {
    "range": {
      "likes": {
        "lt": 10
      }
    }
  }
}
'
複製代碼

你能夠驗證任務:

curl -X GET "localhost:9200/_refresh"
curl -X POST "localhost:9200/twitter/_search?size=0&filter_path=hits.total" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "likes": {
        "lt": 10
      }
    }
  }
}
'
複製代碼

結果是這樣一個合理的total數:

{
  "hits": {
    "total" : {
        "value": 0,
        "relation": "eq"
    }
  }
}
複製代碼

自動切分

您還可讓delete-by-query使用切片滾動自動並行化以在_id上切片。 使用切片指定要使用的切片數:

curl -X POST "localhost:9200/twitter/_delete_by_query?refresh&slices=5" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "likes": {
        "lt": 10
      }
    }
  }
}
'
複製代碼

你能夠驗證任務:

curl -X POST "localhost:9200/twitter/_search?size=0&filter_path=hits.total" -H 'Content-Type: application/json' -d'
{
  "query": {
    "range": {
      "likes": {
        "lt": 10
      }
    }
  }
}
'
複製代碼

結果是這樣一個合理的total數:

{
  "hits": {
    "total" : {
        "value": 0,
        "relation": "eq"
    }
  }
}
複製代碼

slices設置爲auto將容許Elasticsearch選擇要使用的切分數。 此設置將使用每一個分片一個切片,達到必定限制。 若是有多個源索引,它將根據具備最小分片數的索引選擇切片數。

slices 添加到_delete_by_query只會自動執行上一節中使用的手動過程,建立子請求,這意味着它有一點奇怪:

  • 你能夠在Task API中查看這些請求。這些子請求切分請求的任務的「子」任務。
  • 爲切分的請求獲取任務狀態只包含已完成片的狀態。
  • 這些子請求能夠單獨尋址,用於取消和從新節流等操做。
  • slices從新節流請求將按比例從新節流未完成的子請求。
  • slices取消請求將取消每一個子請求。
  • 因爲slices的性質,每一個子請求不會獲得均勻的處理分佈。全部文檔都會被處理,可是子請求的處理可能比子請求處理更多。指望更大的片具備更均勻的分佈。
  • slices的請求上的requests_per_secondsize等參數按比例分佈到每一個子請求。結合上面關於分佈不均勻的觀點,您應該得出結論:使用帶slicessize可能不會致使確切大小的文檔被刪除。
  • 每一個子請求都得到源索引的稍微不一樣的快照,儘管這些快照幾乎是同時獲取的。
選擇切分的數量

若是自動切片,將slices設置爲auto將爲大多數索引選擇一個合理的數字。若是您正在手動切片或以其餘方式調優自動切片,請使用如下指南。

slices數等於索引中的分片數時,查詢性能最有效。 若是該數字很大(例如,500),請選擇較小的數字,由於太多的slices會損害性能。 設置高於分片數量的slices一般不會提升效率並增長開銷。

刪除性能隨着slices的數量在可用資源之間線性擴展。

查詢或刪除性能是否在運行時占主導地位取決於從新索引的文檔和集羣資源。

Update API

update API容許基於提供的腳本更新文檔。該操做從索引中獲取文檔(與切分並列),運行腳本(使用可選的腳本語言和參數),索引返回結果(還容許刪除或忽略該操做)。它使用版本控制來確保在「get」和「reindex」期間沒有發生更新。

注意,這個操做仍然意味着文檔的徹底重索引,它只是刪除了一些網絡往返,並減小了get和index之間版本衝突的機會。須要啓用_source字段才能使此功能正常工做。

讓咱們索引一個簡單的文檔:

curl -X PUT "localhost:9200/test/_doc/1" -H 'Content-Type: application/json' -d'
{
    "counter" : 1,
    "tags" : ["red"]
}
'
複製代碼
腳本更新

如今咱們能夠執行一個腳原本增長計數:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "ctx._source.counter += params.count",
        "lang": "painless",
        "params" : {
            "count" : 4
        }
    }
}
'
複製代碼

咱們能夠添加一個標籤到標籤列表:(若是標籤存在,它仍會被添加,由於這是一個列表)

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "ctx._source.tags.add(params.tag)",
        "lang": "painless",
        "params" : {
            "tag" : "blue"
        }
    }
}
'
複製代碼

咱們也能夠移除一個標籤從標籤列表。注意,用於刪除標記的Painless 函數將但願刪除的元素的數組索引做爲參數,所以須要更多的邏輯來定位它,避免運行時錯誤。注意,若是標籤在列表中出現超過一次,則只會刪除一次:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "if (ctx._source.tags.contains(params.tag)) { ctx._source.tags.remove(ctx._source.tags.indexOf(params.tag)) }",
        "lang": "painless",
        "params" : {
            "tag" : "blue"
        }
    }
}
'
複製代碼

除了_source以外,經過ctx map能夠得到如下變量:_index_type_id_version_routing_now(當前時間戳)。

也能夠添加一個新字段到文檔:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : "ctx._source.new_field = \u0027value_of_new_field\u0027"
}
'
複製代碼

或者從文檔中移除一個字段:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : "ctx._source.remove(\u0027new_field\u0027)"
}
'
複製代碼

甚至咱們能夠改變已執行的操做。這個例子若是tags字段包含green,則會刪除文檔,不然不會有任何操做。(noop)

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = \u0027delete\u0027 } else { ctx.op = \u0027none\u0027 }",
        "lang": "painless",
        "params" : {
            "tag" : "green"
        }
    }
}
'
複製代碼
使用部分文檔更新

update API也支持傳入部分文檔,它將被合併到現有的文檔中(簡單的遞歸合併、對象的內部合併、替換核心「key/value」和數組)。要徹底替換現有文檔,應該使用IndexAPI。如下部分更新向現有文檔添加了一個新字段:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "doc" : {
        "name" : "new_name"
    }
}
'
複製代碼

若是docscript都被指定了,doc將會被忽略。最好是將部分文檔的字段對放在腳本中。

檢測等待更新

若是doc被指定,而且值將與現有的_source合併。默認狀況下,不改變任何東西的更新檢測它們不改變任何東西,並返回「result」:「noop」,以下所示:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "doc" : {
        "name" : "new_name"
    }
}
'
複製代碼

若是在發送請求以前namenew_name,則忽略整個更新請求。 若是忽略請求,響應中的result元素將返回noop。

{
   "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
   },
   "_index": "test",
   "_type": "_doc",
   "_id": "1",
   "_version": 7,
   "result": "noop"
}
複製代碼

你能夠經過"detect_noop": false來禁用這個行爲:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "doc" : {
        "name" : "new_name"
    },
    "detect_noop": false
}
'
複製代碼
Upserts

若是文檔不存在,upsert元素的內容將做爲新文檔插入。若是文檔確實存在,則執行腳本:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "script" : {
        "source": "ctx._source.counter += params.count",
        "lang": "painless",
        "params" : {
            "count" : 4
        }
    },
    "upsert" : {
        "counter" : 1
    }
}
'
複製代碼

scripted_upsert

若是您但願腳本運行,不管文檔是否存在 - 即腳本處理初始化文檔而不是upsert元素 - 將scripted_upsert設置爲true

curl -X POST "localhost:9200/sessions/_update/dh3sgudg8gsrgl" -H 'Content-Type: application/json' -d'
{
    "scripted_upsert":true,
    "script" : {
        "id": "my_web_session_summariser",
        "params" : {
            "pageViewEvent" : {
                "url":"foo.com/bar",
                "response":404,
                "time":"2014-01-01 12:32"
            }
        }
    },
    "upsert" : {}
}
'
複製代碼

doc_as_upsert

doc_as_upsert設置爲true將使用doc的內容做爲upsert值,而不是發送部分doc加上upsert文檔:

curl -X POST "localhost:9200/test/_update/1" -H 'Content-Type: application/json' -d'
{
    "doc" : {
        "name" : "new_name"
    },
    "doc_as_upsert" : true
}
'
複製代碼
參數

update操做支持下面幾個參數:

retry_on_conflict

​ 在更新的get和indexing 階段之間,另外一個進程可能已經更新了相同的文檔。默認狀況下,更新將失敗,出現版本衝突異常。retry_on_conflict參數控制在最終拋出異常以前重試更新的次數。

routing

​ 路由用於將更新請求路由到正確的分片,並在更新的文檔不存在時爲upsert請求設置路由。 不能用於更新現有文檔的路由。

timeout

​ 分片變成可用狀態的超時等待時間。

wait_for_active_shards

​ 在繼續更新操做以前須要處於活動狀態的分片副本數。

refresh

​ 控制什麼時候此請求所作的更改對搜索可見。

_source

​ 容許控制是否以及如何在響應中返回更新的源。 默認狀況下,不會返回更新的源。

version

​ 更新API在內部使用Elasticsearch版本控制支持,以確保在更新期間文檔不會更改。 您可使用version參數指定僅在文檔版本與指定版本匹配時才更新文檔。

更新API不支持內部版本之外的版本控制

更新API不支持外部(版本類型external和external_gte)或強制(版本類型強制)版本控制,由於它會致使Elasticsearch版本號與外部系統不一樣步。 請改用index API。

if_seq_no if_primary_term

更新操做能夠是有條件的,只有在爲文檔的最後一次修改分配了if_seq_noif_primary_term參數指定的值時才能執行。 若是檢測到不匹配,則操做將致使VersionConflictException和狀態代碼409。

經過Query API來更新

_update_by_query的最簡單用法只是對索引中的每一個文檔執行更新而不更改源。 這對於獲取新屬性或其餘一些在線映射更改頗有用。 下面是API:

curl -X POST "localhost:9200/twitter/_update_by_query?conflicts=proceed"
複製代碼

返回的結果爲:

{
  "took" : 147,
  "timed_out": false,
  "updated": 120,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "total": 120,
  "failures" : [ ]
}
複製代碼

_update_by_query在索引啓動時獲取索引的快照,並使用內部版本控制索引它的內容。這意味着若是文檔在拍攝快照的時間和處理索引請求之間發生更改,則會出現版本衝突。若是版本匹配,文檔會被更新,而且版本號會增長。

由於internal 版本控制不支持0做爲有效的版本號,文檔的版本號等於0不能使用_update_by_query來更新,這樣的請求會失敗。

因爲_update_by_query終止而致使的查詢和更新失敗,會在響應體裏返回一個failures 字段。已經執行的更新仍然有效。換句話說,這個過程沒有回滾,只能停止。當第一個故障致使停止時,失敗的批量請求返回的全部故障都將在failure元素中返回,所以,可能存在至關多的失敗實體。

若是隻想簡單的計算版本衝突,而且不是因爲_update_by_query引發的停止,你能夠設置在url中設置conflicts=proceed,或者在請求體中"conflicts": "proceed"。第一個示例之因此這樣作,是由於它只是試圖獲取一個在線映射更改,而版本衝突僅僅意味着在_update_by_query的開始時間和它試圖更新文檔的時間之間更新了衝突文檔。這是有用的,由於更新將得到在線映射更新。

再回到API,這將從twitter索引更新到tweets:

curl -X POST "localhost:9200/twitter/_update_by_query?conflicts=proceed"
複製代碼

你還可使用Query DSL來對_update_by_query進行限制。下面的例子將會爲用戶kimchy更新twitter中的全部文檔:

curl -X POST "localhost:9200/twitter/_update_by_query?conflicts=proceed" -H 'Content-Type: application/json' -d'
{
#查詢必須傳入一個query的key,或者也能夠傳入一個q,就像SearchApi同樣
  "query": { 
    "term": {
      "user": "kimchy"
    }
  }
}
'
複製代碼

到目前爲止,咱們只更新了文檔,而沒有更改它們的source。這確實對添加新屬性頗有用。_update_by_query支持更新文檔的腳本。這將增長kimchy全部tweet上的like字段:

curl -X POST "localhost:9200/twitter/_update_by_query" -H 'Content-Type: application/json' -d'
{
  "script": {
    "source": "ctx._source.likes++",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
'
複製代碼

就像在Update API中同樣,您能夠設置ctx.op更改執行的操做:

noop 若是你的腳本不做任何更改,能夠設置ctx.op="noop"。這將致使_update_by_query從其更新中省略該文檔。noop操做將在響應體中的noop計數器中展現。
delete 若是你的腳本必須刪除,能夠設置ctx.op="delete"。刪除操做將在響應體中的deleted計數器中展現。

將ctx.op設置爲其餘任何內容都是錯誤的。 在ctx中設置任何其餘字段是錯誤的。

請注意,咱們中止指定conflict = proceed。 在這種狀況下,咱們但願版本衝突停止該過程,以便咱們能夠處理失敗。

此API不容許您改變它關聯的文檔,只需修改它們的source。 這是故意的! 咱們沒有規定從原始位置刪除文檔。

也能夠在多個索引上同時完成這一切,就像搜索API:

curl -X POST "localhost:9200/twitter,blog/_update_by_query"
複製代碼

若是提供routing,則將路由複製到滾動查詢,將過程限制爲匹配該路由值的分片:

curl -X POST "localhost:9200/twitter/_update_by_query?routing=1"
複製代碼

默認狀況下,_update_by_query使用滾動批次爲1000。您可使用scroll_size URL參數更改批大小:

curl -X POST "localhost:9200/twitter/_update_by_query?scroll_size=100"
複製代碼

_update_by_query也能夠經過指定管道來使用Ingest節點功能:

curl -X PUT "localhost:9200/_ingest/pipeline/set-foo" -H 'Content-Type: application/json' -d'
{
  "description" : "sets foo",
  "processors" : [ {
      "set" : {
        "field": "foo",
        "value": "bar"
      }
  } ]
}
'
curl -X POST "localhost:9200/twitter/_update_by_query?pipeline=set-foo"
複製代碼
URL參數

除了像pretty這樣的標準參數以外,查詢API的刪除還支持refreshwait_for_completionwait_for_active_shardstimeoutscroll

發送refresh將在請求完成後刷新查詢刪除中涉及的全部分片。 這與delete API的refresh參數不一樣,後者只會刷新收到刪除請求的分片。 與delete API不一樣,它不支持wait_for

若是請求包含wait_for_completion = false,則Elasticsearch將執行一些預檢查,啓動請求,而後返回可與Tasks API一塊兒使用的任務,以取消或獲取任務的狀態。 Elasticsearch還將在.tasks / task / $ {taskId}中建立此任務的記錄做爲文檔。 這是你的保留或刪除你認爲合適的。 完成後將會刪除它,以便Elasticsearch能夠回收它使用的空間。

wait_for_active_shards控制在繼續請求以前必須激活分片的副本數。 timeout指示每一個寫入請求等待不可用分片可用的時間。 二者都徹底適用於Bulk API中的工做方式。 因爲_delete_by_query使用滾動搜索,您還能夠指定scroll參數來控制search context保持活動的時間,例如?scroll=10m。 默認狀況下,它是5分鐘。

requests_per_second能夠設置爲任何正十進制數(1.4,6,1000等),並經過在等待時間內填充每一個批次來限制查詢刪除發出批量刪除操做的速率。 能夠經過將requests_per_second設置爲-1來禁用限制。

節流是經過在批之間等待來完成的,這樣就能夠給_delete_by_query內部使用的滾動設置一個考慮填充的超時。填充時間是批大小除以requests_per_second和寫入時間之間的差額。默認狀況下批處理大小爲1000,因此若是requests_per_second被設置爲500:

target_time = 1000 / 500 per second = 2 seconds
wait_time = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds
複製代碼

因爲批處理是做爲單個_bulk請求發出的,所以較大的批處理將致使Elasticsearch建立許多請求,而後等待一段時間再啓動下一個請求集。這是突發的而不是平滑的。默認值是-1。

響應體

響應結果就像下面的那樣:

{
  "took" : 147,
  "timed_out": false,
  "total": 5,
  "updated": 5,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "failures" : [ ]
}
複製代碼

took

​ 整個操做從開始到結束的毫秒數。

time_out

​ 若是在update by query執行期間執行的任何請求超時,則將此標誌設置爲true。

total

​ 成功執行的文檔總數

updated

​ 成功更新的文檔總數

deleted

​ 成功刪除的文檔總數

batches

​ 經過查詢更新回滾的滾動響應數。

version_conflicts

​ 按查詢更新所命中的版本衝突數。

noops

​ 因爲用於update by query的腳本返回了ctx.op的noop值而被忽略的文檔數量。

retries

​ 按查詢更新所嘗試的重試次數。bulk是重試的批量操做的數量,search是重試的搜索操做的數量。

throttled_millis

​ 符合requests_per_second的請求毫秒數

requests_per_second

​ 在update by query期間每秒有效執行的請求數。

throttled_until_millis

​ 在_update_by_query響應中,此字段應始終等於零。 它只在使用Task API時有意義,它表示下一次(自epoch以來的毫秒數),爲了符合requests_per_second,將再次執行受限制的請求。

failures

​ 若是流程中存在任何不可恢復的錯誤,則會出現一系列故障。若是這不是空的,那麼請求就會由於這些失敗而停止。使用batch實現update by query,任何失敗都會致使整個進程停止,可是當前batch中的全部失敗都會收集到數組中。您可使用conflicts選項來防止reindex在版本衝突上停止。

使用Task API

你可使用Task API來獲取運行delete by query請求的狀態:

curl -X GET "localhost:9200/_tasks?detailed=true&actions=*/delete/byquery"
複製代碼

響應結果:

{
  "nodes" : {
    "r1A2WoRbTwKZ516z6NEs5A" : {
      "name" : "r1A2WoR",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "attributes" : {
        "testattr" : "test",
        "portsfile" : "true"
      },
      "tasks" : {
        "r1A2WoRbTwKZ516z6NEs5A:36619" : {
          "node" : "r1A2WoRbTwKZ516z6NEs5A",
          "id" : 36619,
          "type" : "transport",
          "action" : "indices:data/write/delete/byquery",
          "status" : {    
            "total" : 6154,
            "updated" : 0,
            "created" : 0,
            "deleted" : 3500,
            "batches" : 36,
            "version_conflicts" : 0,
            "noops" : 0,
            "retries": 0,
            "throttled_millis": 0
          },
          "description" : ""
        }
      }
    }
  }
}
複製代碼

該對象包含實際狀態。 它就像響應JSON同樣,增長了total 字段。 totalreindex指望執行的操做總數。 您能夠經過添加updatedcreateddeleted的字段來估計進度。 當它們的總和等於total字段時,請求將結束。

經過Task id能夠直接查看Task:

curl -X GET "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619"
複製代碼

此API的優勢是它與wait_for_completion = false集成,透明地返回已完成任務的狀態。 若是任務完成而且在其上設置了wait_for_completion = false,那麼它將返回resulterror 字段。 此功能的代價是wait_for_completion = false.tasks / task / $ {taskId}建立的文檔。 您能夠刪除該文檔。

使用Cancel Tash API

全部的update by query能經過task cancel API被關閉:

curl -X POST "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel"
複製代碼

Task ID能夠經過task API來找到。

取消操做應該快速的發生,可是有時可能會幾秒。上面的任務狀態API將繼續按查詢任務列出delete,直到該任務檢查它是否已被取消並自行終止。

Rethrottling

可使用_rethrottle API經過查詢在正在運行的刪除時更改requests_per_second的值:

curl -X POST "localhost:9200/_update_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1"
複製代碼

經過Task id能夠直接查看Task.

就像在查詢API的刪除中設置它同樣,requests_per_second能夠是-1來禁用限制,也能夠是1.7或12之類的任何十進制數來限制到該級別。 加速查詢的Rethrottling會當即生效,但從新啓動會減慢查詢速度,這將在完成當前批處理後生效。 這能夠防止滾動超時。

切分請求

按查詢更新支持分割滾動以並行化更新過程。 這種並行化能夠提升效率,並提供一種方便的方法將請求分解爲更小的部分。

手動切分

經過對每一個請求提供一個切分id和切分的總數來手動的切分update by query

curl -X POST "localhost:9200/twitter/_update_by_query" -H 'Content-Type: application/json' -d'
{
  "slice": {
    "id": 0,
    "max": 2
  },
  "script": {
    "source": "ctx._source[\u0027extra\u0027] = \u0027test\u0027"
  }
}
'
curl -X POST "localhost:9200/twitter/_update_by_query" -H 'Content-Type: application/json' -d'
{
  "slice": {
    "id": 1,
    "max": 2
  },
  "script": {
    "source": "ctx._source[\u0027extra\u0027] = \u0027test\u0027"
  }
}
'

複製代碼

你能夠驗證任務:

curl -X GET "localhost:9200/_refresh"
curl -X POST "localhost:9200/twitter/_search?size=0&q=extra:test&filter_path=hits.total"
複製代碼

結果是這樣一個合理的total數:

{
  "hits": {
    "total": {
        "value": 120,
        "relation": "eq"
    }
  }
}
複製代碼

自動切分

您還可讓update-by-query使用切片滾動自動並行化以在_id上切片。 使用切片指定要使用的切片數:

curl -X POST "localhost:9200/twitter/_update_by_query?refresh&slices=5" -H 'Content-Type: application/json' -d'
{
  "script": {
    "source": "ctx._source[\u0027extra\u0027] = \u0027test\u0027"
  }
}
'

複製代碼

你能夠驗證任務:

curl -X POST "localhost:9200/twitter/_search?size=0&q=extra:test&filter_path=hits.total"
複製代碼

結果是這樣一個合理的total數:

{
  "hits": {
    "total": {
        "value": 120,
        "relation": "eq"
    }
  }
}
複製代碼

slices設置爲auto將容許Elasticsearch選擇要使用的切分數。 此設置將使用每一個分片一個切片,達到必定限制。 若是有多個源索引,它將根據具備最小分片數的索引選擇切片數。

slices 添加到_delete_by_query只會自動執行上一節中使用的手動過程,建立子請求,這意味着它有一點奇怪:

  • 你能夠在Task API中查看這些請求。這些子請求切分請求的任務的「子」任務。
  • 爲切分的請求獲取任務狀態只包含已完成片的狀態。
  • 這些子請求能夠單獨尋址,用於取消和從新節流等操做。
  • slices從新節流請求將按比例從新節流未完成的子請求。
  • slices取消請求將取消每一個子請求。
  • 因爲slices的性質,每一個子請求不會獲得均勻的處理分佈。全部文檔都會被處理,可是子請求的處理可能比子請求處理更多。指望更大的片具備更均勻的分佈。
  • slices的請求上的requests_per_secondsize等參數按比例分佈到每一個子請求。結合上面關於分佈不均勻的觀點,您應該得出結論:使用帶slicessize可能不會致使確切大小的文檔被刪除。
  • 每一個子請求都得到源索引的稍微不一樣的快照,儘管這些快照幾乎是同時獲取的。
選擇切分的數量

若是自動切片,將slices設置爲auto將爲大多數索引選擇一個合理的數字。若是您正在手動切片或以其餘方式調優自動切片,請使用如下指南。

slices數等於索引中的分片數時,查詢性能最有效。 若是該數字很大(例如,500),請選擇較小的數字,由於太多的slices會損害性能。 設置高於分片數量的slices一般不會提升效率並增長開銷。

更新性能隨着slices的數量在可用資源之間線性擴展。

查詢或更新性能是否在運行時占主導地位取決於從新索引的文檔和集羣資源。

獲取新屬性

假設您建立了一個沒有動態映射的索引,用數據填充它,而後添加一個映射值來從數據中獲取更多字段:

curl -X PUT "localhost:9200/test" -H 'Content-Type: application/json' -d'
{
  "mappings": {
 #意味着新字段不會被索引,只會存儲在_source中
    "dynamic": false,   
    "properties": {
      "text": {"type": "text"}
    }
  }
}
'
curl -X POST "localhost:9200/test/_doc?refresh" -H 'Content-Type: application/json' -d'
{
  "text": "words words",
  "flag": "bar"
}
'
curl -X POST "localhost:9200/test/_doc?refresh" -H 'Content-Type: application/json' -d'
{
  "text": "words words",
  "flag": "foo"
}
'
# 這個更新映射到新添加的flag字段,要獲取新字段,您必須使用它從新索引全部文檔。
curl -X PUT "localhost:9200/test/_mapping" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "text": {"type": "text"},
    "flag": {"type": "text", "analyzer": "keyword"}
  }
}
'
複製代碼

使用flag字段搜索不會找到內容:

curl -X POST "localhost:9200/test/_search?filter_path=hits.total" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "flag": "foo"
    }
  }
}
'
複製代碼

響應結果:

{
  "hits" : {
    "total": {
        "value": 0,
        "relation": "eq"
    }
  }
}
複製代碼

可是你能夠發出一個_update_by_query請求來獲取新映射:

curl -X POST "localhost:9200/test/_update_by_query?refresh&conflicts=proceed"
curl -X POST "localhost:9200/test/_search?filter_path=hits.total" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "flag": "foo"
    }
  }
}
'
複製代碼
{
  "hits" : {
    "total": {
        "value": 1,
        "relation": "eq"
    }
  }
}
複製代碼

在向多字段添加字段時,您能夠執行徹底相同的操做。

Multi GET API

Multi get API基於索引,類型,(可選)和id(或者路由)返回多個文檔。響應包括一個docs數組,其中包含全部獲取的文檔,按照multi-get請求對應的順序排列(若是某個特定get出現失敗,則在響應中包含一個包含此錯誤的對象)。成功get的結構在結構上相似於get API提供的文檔。

下面是例子:

curl -X GET "localhost:9200/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'
複製代碼

mget端點也能夠用於索引(在這種狀況下,在請求體中不須要它):

curl -X GET "localhost:9200/test/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'
複製代碼

用於類型:

curl -X GET "localhost:9200/test/_doc/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_id" : "1"
        },
        {
            "_id" : "2"
        }
    ]
}
'
複製代碼

在這個例子中,ids元素能夠直接用來簡化請求:

curl -X GET "localhost:9200/test/_doc/_mget" -H 'Content-Type: application/json' -d'
{
    "ids" : ["1", "2"]
}
'
複製代碼
過濾Source

默認的,_source會被每一個文檔返回(若是存儲),相似get API,可使用_source參數只檢索_source的一部分(或者根本不檢索)。你還可使用url參數,_source,_source_includes,_source_excludes,來指定默認值。當沒有針對每一個文檔的指令時,會使用默認值。

例如:

curl -X GET "localhost:9200/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "_source" : false
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2",
            "_source" : ["field3", "field4"]
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "3",
            "_source" : {
                "include": ["user"],
                "exclude": ["user.location"]
            }
        }
    ]
}
'
複製代碼
字段

能夠爲每一個要獲取的文檔指定要檢索的特定存儲字段,相似於get API的stored_fields參數。例如:

curl -X GET "localhost:9200/_mget" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "stored_fields" : ["field1", "field2"]
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2",
            "stored_fields" : ["field3", "field4"]
        }
    ]
}
'
複製代碼

或者,您能夠在查詢字符串中指定stored_fields參數做爲應用於全部文檔的默認值。

curl -X GET "localhost:9200/test/_doc/_mget?stored_fields=field1,field2" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
        # 返回field1和field2
            "_id" : "1" 
        },
        {
        # 返回field3和field4
            "_id" : "2",
            "stored_fields" : ["field3", "field4"] 
        }
    ]
}
'
複製代碼
路由

你還能夠指定一個路由值來做爲參數:

curl -X GET "localhost:9200/_mget?routing=key1" -H 'Content-Type: application/json' -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "routing" : "key2"
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'
複製代碼

在此示例中,將從對應於路由密鑰key1的分片中提取文檔test / _doc / 2,可是將從對應於路由密鑰key2的分片中提取文檔test / _doc / 1。

在本例中,文檔test / _doc / 2將從與路由鍵key1對應的切分中獲取,可是文檔`test / _doc / 1將從與路由鍵key2對應的切分中獲取。

部分響應

爲確保快速響應,若是一個或多個分片失敗,多重獲取API將響應部分結果。 有關更多信息,請參閱Shard故障

Bulk API

批量API能夠在一個API調用中執行許多索引/刪除操做,這能夠大大提升索引速度。

/_bulk是其路徑,而且使用換行符來分割JSON結構。

action_and_meta_data\n
optional_source\n
action_and_meta_data\n
optional_source\n
....
action_and_meta_data\n
optional_source\n
複製代碼

注意:

最後一行數據必須以換行符\ n結尾。 每一個換行符前面都有一個回車符\ r \ n。 向此路徑發送請求時,Content-Type標頭應設置爲application / x-ndjson。

總共有4個動做,分別是index,create,delete,updateindexcreate指望下一行的source,而且與標準index API的op_type參數具備相同的語義(即,若是已存在具備相同索引的文檔,則create將失敗,而index將根據須要添加或替換文檔)。 delete不指望下一行中的source,而且具備與標準刪除API相同的語義。 update指望在下一行指定部分doc,upsert和script及其選項。

若是你提供了text文件輸入到curl,你必須使用--data-binary標識而不是普通的-d,後面不容許保留新行,例如:

$ cat requests
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
$ curl -s -H "Content-Type: application/x-ndjson" -XPOST localhost:9200/_bulk --data-binary "@requests"; echo
{"took":7, "errors": false, "items":[{"index":{"_index":"test","_type":"_doc","_id":"1","_version":1,"result":"created","forced_refresh":false}}]}
複製代碼

由於這個格式使用的是字面意義的\n‘s做爲分隔符,請確保JSON操做和源代碼沒有被很好地打印出來。下面是一個正確的批量命令序列的例子:

curl -X POST "localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
'
複製代碼

這個批量操做的結果是:

{
   "took": 30,
   "errors": false,
   "items": [
      {
         "index": {
            "_index": "test",
            "_type": "_doc",
            "_id": "1",
            "_version": 1,
            "result": "created",
            "_shards": {
               "total": 2,
               "successful": 1,
               "failed": 0
            },
            "status": 201,
            "_seq_no" : 0,
            "_primary_term": 1
         }
      },
      {
         "delete": {
            "_index": "test",
            "_type": "_doc",
            "_id": "2",
            "_version": 1,
            "result": "not_found",
            "_shards": {
               "total": 2,
               "successful": 1,
               "failed": 0
            },
            "status": 404,
            "_seq_no" : 1,
            "_primary_term" : 2
         }
      },
      {
         "create": {
            "_index": "test",
            "_type": "_doc",
            "_id": "3",
            "_version": 1,
            "result": "created",
            "_shards": {
               "total": 2,
               "successful": 1,
               "failed": 0
            },
            "status": 201,
            "_seq_no" : 2,
            "_primary_term" : 3
         }
      },
      {
         "update": {
            "_index": "test",
            "_type": "_doc",
            "_id": "1",
            "_version": 2,
            "result": "updated",
            "_shards": {
                "total": 2,
                "successful": 1,
                "failed": 0
            },
            "status": 200,
            "_seq_no" : 3,
            "_primary_term" : 4
         }
      }
   ]
}
複製代碼

路徑是/_bulk/{index}/_bulk。提供索引時,默認狀況下,索引將用於未顯式提供索引的Bulk。

格式說明,這裏的想法是讓處理過程儘量快。因爲一些操做將被重定向到其餘節點上的其餘切分,所以只有action_meta_data在接收節點端被解析。

使用此協議的客戶端庫應該嘗試在客戶端嘗試相似的操做,並儘量減小緩衝。

批量操做的結果是一個大的JSON結果數據,每一個操做結果的順序和請求中的順序是一致的。 單個操做的失敗不會影響剩餘的操做。

在單個批量調用中沒有要執行的操做的「correct」數量。您應該嘗試不一樣的設置,以找到適合您特定工做負載的最佳大小。

若是使用HTTP API,請確保客戶機不發送HTTP chunks,由於這會下降速度。

樂觀併發控制

批量API調用中的每一個indexdelete操做能夠在其各自的操做和元數據行中添加if_seq_noif_primary_term參數。 if_seq_noif_primary_term參數根據對現有文檔的最後修改來控制操做的執行方式。 有關更多詳細信息,請參閱樂觀併發控制

版本控制

每一個bulk項均可以使用version字段引入版本值。 它會根據_version映射自動跟蹤index/delete操做的行爲。 它還支持version_type

路由

每一個bulk項均可以使用routing字段來引入路由值,它自動遵循基於_routing映射的index/delete操做的行爲。

等待活動分區

在進行批量調用時,能夠將wait_for_active_shards參數設置爲在開始處理批量請求以前須要激活最少數量的碎片副本。

刷新

控制什麼時候此請求所作的更改對搜索可見。

只有收到bulk請求的分片纔會受到刷新的影響。 想象一下_bulk?refresh = wait_for請求,其中包含三個文檔,這些文檔剛好被路由到具備五個分片的索引中的不一樣分片。 請求只會等待這三個分片刷新。 構成索引的其餘兩個分片根本不參與_bulk請求。

更新

使用update操做時,retry_on_conflict可用做操做自己的字段(不在額外的有效payload line中),以指定在版本衝突的狀況下應重試更新的次數。

update操做有效內容支持如下選項:doc(部分文檔),upsert,doc_as_upsert,script,params(用於腳本),lang(用於腳本)和_source。 更新操做的示例:

curl -X POST "localhost:9200/_bulk" -H 'Content-Type: application/json' -d'
{ "update" : {"_id" : "1", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"} }
{ "update" : { "_id" : "0", "_index" : "index1", "retry_on_conflict" : 3} }
{ "script" : { "source": "ctx._source.counter += params.param1", "lang" : "painless", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
{ "update" : {"_id" : "2", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }
{ "update" : {"_id" : "3", "_index" : "index1", "_source" : true} }
{ "doc" : {"field" : "value"} }
{ "update" : {"_id" : "4", "_index" : "index1"} }
{ "doc" : {"field" : "value"}, "_source": true}
'
複製代碼
部分響應

爲確保快速響應,若是一個或多個分片失敗,多重獲取API將響應部分結果。 有關更多信息,請參閱Shard故障

Reindex API

Reindex要求爲source index中的全部文檔啓用_source

Reindex不會嘗試設置目標索引,而且不會拷貝source index 中的設置。您應該在運行_reindex操做以前設置目標索引,包括設置映射,分片數量,副本等

Reindex的最基本形式只是將文檔從一個索引複製到另外一個索引。下面的例子將拷貝文檔twitter索引到new_twitter索引中:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

返回結果以下:

{
  "took" : 147,
  "timed_out": false,
  "created": 120,
  "updated": 0,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "total": 120,
  "failures" : [ ]
}
複製代碼

就像_update_by_queryreindex獲取一個source index 的快照,可是目標必須是一個不一樣的索引,因此不會出現版本衝突。能夠像索引API同樣配置dest元素來控制樂觀併發控制。僅僅須要省略version_type(如上所屬)或者設置它爲internal 。都會致使Elasticsearch將文檔盲目的轉儲到目標中,覆蓋任何碰巧具備相同類型和id的文檔:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "internal"
  }
}
'
複製代碼

設置version_typeexternal 將致使Elasticsearch保存源文件的版本,建立缺失的文檔,並更新目標索引中比源索引中版本更舊的文檔:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "external"
  }
}
'
複製代碼

設置op_typecreate將致使_reindex在目標索引中只建立丟失的文檔,全部已存在的文檔將會致使版本衝突。

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}
'
複製代碼

默認的,版本衝突會停止_reindex。當版本衝突時,conflicts請求體參數能夠指導_reindex來處理下一個文檔。須要重要注意的時,經過conflicts參數處理其餘錯誤類型是不受影響的,當在請求體中設置 "conflicts": "proceed"_reindex將繼續處理版本衝突,並返回所遇到的版本衝突計數:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "conflicts": "proceed",
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}
'
複製代碼

您能夠經過向source添加查詢來限制文檔。這將只複製由kimchy發出的tweetnew_twitter:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter",
    "query": {
      "term": {
        "user": "kimchy"
      }
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

indexsource是一個列表,在一個請求中,容許你從大量sources中拷貝。下面的例子將從twitterblog文檔中拷貝文檔:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": ["twitter", "blog"]
  },
  "dest": {
    "index": "all_together"
  }
}
'
複製代碼

Reindex API不會處理ID衝突,所以最後編寫的文檔將「win」,但順序一般不可預測,所以依賴此行爲並非一個好主意。 而是使用腳本確保ID是惟一的。

經過設置size來限制處理文檔的數量這,將會從twitter拷貝一個單獨的文檔到new _twitter:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "size": 1,
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

若是你想要twitter索引中的特定文檔集,你須要使用sort。排序使滾動效率下降,但在某些狀況下,它是值得的。 若是可能,請選擇更具選擇性的查詢來進行大小和排序。 這會將10000個文件從twitter複製到new_twitter:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "size": 10000,
  "source": {
    "index": "twitter",
    "sort": { "date": "desc" }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

source部分支持搜索請求中支持的全部元素。 例如,可使用source過濾從新索引原始文檔中的一部分字段,以下所示:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter",
    "_source": ["user", "_doc"]
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

_update_by_query, _reindex支持腳本修改文檔,和_update_by_query不一樣,它容許修改文檔的metadata,這個例子顛覆了源文檔的版本:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "external"
  },
  "script": {
    "source": "if (ctx._source.foo == \u0027bar\u0027) {ctx._version++; ctx._source.remove(\u0027foo\u0027)}",
    "lang": "painless"
  }
}
'
複製代碼

就像在_update_by_query中同樣,您能夠設置ctx.op來更改在目標索引上執行的操做:

noop

​ 若是腳本決定不須要在目標索引中索引文檔,則設置ctx.op = "noop"。此no操做將在響應體中的noop計數器中報告。

delete

​ 若是腳本決定必須從目標索引中刪除文檔,則設置ctx.op = "delete"。刪除操做將在響應主體的已刪除計數器中報告。

設置ctx.op爲其餘,或者在CTX中設置任何其餘字段,將會返回錯誤。

你能夠改變:

  • _id
  • _index
  • _version
  • _routing

_version設置爲null或將它從ctx映射中清除,就像沒有在索引請求中發送版本同樣;它會致使在目標索引中覆蓋文檔,而無論目標上的版本或在_reindex請求中使用的版本類型。

默認狀況下,若是_reindex看到帶有路由的文檔,則除非腳本更改了路由,不然將保留路由。 您能夠在dest請求上設置路由以更改此設置:

keep

​ 將針對每一個匹配發送的批量請求的路由設置爲匹配上的路由。 這是默認值。

discard

​ 將爲每一個匹配發送的批量請求上的路由設置爲null。

=<some text>

​ 將爲每一個匹配發送的批量請求上的路由設置爲=以後的全部文本。

例如,您可使用如下請求將全部文檔從具備公司名稱cat的源索引複製到路由設置爲cat的dest索引中。

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "source",
    "query": {
      "match": {
        "company": "cat"
      }
    }
  },
  "dest": {
    "index": "dest",
    "routing": "=cat"
  }
}
'
複製代碼

默認狀況下,reindex使用的滾動批數爲1000。你能夠在source元素中設置size字段來改變批數大小。

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "source",
    "size": 100
  },
  "dest": {
    "index": "dest",
    "routing": "=cat"
  }
}
'
複製代碼

Reindex還可使用經過指定pipeline來使用Ingest node特色,像下面這樣:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "source"
  },
  "dest": {
    "index": "dest",
    "pipeline": "some_ingest_pipeline"
  }
}
'
複製代碼
從遠程Reindex

Reindex支持從遠程Elasticsearch集羣reindexing

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}
'
複製代碼

host參數必須包含協議,主機,端口(例如:http:/otherHost:9200)和可選路徑(例如:http:/otherHost:9200)。usernamepassword是可選的,若是填寫了username和password,那麼_reindex將會使用他們做爲鏈接到遠程Elasticsearch集羣的基礎驗證。使用基自己份驗證時務必使用https,不然密碼將以純文本格式發送。有一系列設置可用來配置https鏈接的行爲。

遠程主機必須在elasticsearch.yml中使用reindex.remote.whitelist屬性指定白名單。能夠將其設置爲逗號分隔的容許遠程主機和端口組合列表(例如: otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*),協議能夠忽略,僅主機和端口是必須的例如:

reindex.remote.whitelist: "otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*"
複製代碼

必須在節點上配置白名單來配合reindex。

要啓用發送到舊版本Elasticsearch的查詢,無需驗證或修改便可將查詢參數直接發送到遠程主機。

從遠程集羣節點Reindexing不支持手動或者自動切分。

從遠程服務器Reindex使用堆上緩衝區,默認最大大小爲100mb。若是遠程索引包含很是大的文檔,則你須要更小的批數size,下面的例子設置批數大小爲10這是很是很是小的。

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200"
    },
    "index": "source",
    "size": 10,
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}
'
複製代碼

還可使用socket_timeout字段設置遠程鏈接上的套接字讀取超時,使用connect_timeout字段設置鏈接超時。二者默認都是30秒。下面這個例子,設置套接字讀取超時爲1分鐘,鏈接超時設置爲10秒。

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "socket_timeout": "1m",
      "connect_timeout": "10s"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}
'
複製代碼
配置SSL參數

從遠程Reindex支持SSL設置,這些設置必須在elasticsearch.yml中配置,除了安全設置,安全設置添加在Elasticsearch KeyStore中。配置SSL不會在_reindex請求體中:

支持下面的設置:

reindex.ssl.certificate_authorities

​ 應受信任的PEM編碼證書文件的路徑列表。你不能同時指定reindex.ssl.certificate_authoritiesreindex.ssl.truststore.path.

reindex.ssl.truststore.path

​ Java keyStore文件的路徑,包含受信任的證書。這個信任庫能夠是JKS或者PKCS#12格式。你不能同時指定reindex.ssl.certificate_authoritiesreindex.ssl.truststore.path.

reindex.ssl.truststore.password

​ 信任庫的密碼(reindex.ssl.truststore.path),這個設置不能用於reindex.ssl.truststore.secure_password

reindex.ssl.truststore.secure_password (Source)

​ 信任庫的密碼(reindex.ssl.truststore.path),這個設置不能用於reindex.ssl.truststore.secure_password

reindex.ssl.truststore.type

​ 信任庫的類型 (reindex.ssl.truststore.path),必須是jks 或者PKCS12其中的一個。若是信任庫路徑以".p12", ".pfx" or "pkcs12"結尾,這個設置默認是PKCS12,不然默認爲JKS

reindex.ssl.verification_mode

​ 指示用於防止中間人攻擊和僞造證書的驗證類型。其中一個是full驗證主機名和證書路徑,certificate驗證正路路徑,可是不驗證主機名,null不進行驗證,在生產環境中建議使用null,默認爲full

reindex.ssl.certificate

​ 指定用於HTTP客戶端身份驗證(若是遠程集羣須要)的PEM編碼證書(或證書鏈)的路徑,此設置須要reindex.ssl.key也被設置。您不能同時指定reindex.ssl.certificatereindex.ssl.keystore.path

reindex.ssl.key

​ 指定證書用於客戶端驗證PEM解碼私鑰關聯的路徑 (reindex.ssl.certificate)。你不能同時指定reindex.ssl.keyreindex.ssl.keystore.path

reindex.ssl.key_passphrase

​ 若是PEM解碼私鑰是加密的,指定解密PEM解碼私鑰的密碼。不能用於reindex.ssl.secure_key_passphrase

reindex.ssl.secure_key_passphrase(安全)

​ 若是PEM解碼私鑰是加密的,指定解密PEM解碼私鑰的密碼。不能用於reindex.ssl.key_passphrase

reindex.ssl.keystore.path

​ 指定用於HTTP客戶端驗證的keyStore包含私鑰和證書的路徑(若是遠程集羣須要)。keyStore可使用JKSPKCS#12格式。你不能同時指定reindex.ssl.keyreindex.ssl.keystore.path

reindex.ssl.keystore.type

​ keyStore的類型 (reindex.ssl.keystore.path)。必須是jks 或者PKCS12其中的一個。若是信任庫路徑以".p12", ".pfx" or "pkcs12"結尾,這個設置默認是PKCS12,不然默認爲JKS

reindex.ssl.keystore.password

​ keystore的密碼(reindex.ssl.keystore.path),這個設置不能用於reindex.ssl.keystore.secure_password

reindex.ssl.keystore.secure_password (安全)

​ keystore的密碼(reindex.ssl.keystore.path),這個設置不能用於reindex.ssl.keystore.password

reindex.ssl.keystore.key_password

​ 在keystore中用於key的密碼(reindex.ssl.keystore.path)默認爲keystore密碼。這個設置不能用於reindex.ssl.keystore.secure_key_password

reindex.ssl.keystore.secure_key_password(安全)

​ 在keystore中用於key的密碼(reindex.ssl.keystore.path)默認爲keystore密碼。這個設置不能用於reindex.ssl.keystore.key_password

URL參數

除了像pretty這樣的標準參數,ReindexAPI還支持refresh,wait_for_completion, wait_for_active_shards, timeout, scroll, 和 requests_per_second

發送refreshurl參數將致使請求寫入全部已刷新的索引。這個不一樣於IndexAPI的refresh參數,後者只會刷新接收新數據的碎片。也不想IndexAPI,它不支持wait_for

在請求中包含wait_for_completion=false,Elasticsearch將會執行一些預檢查,開始請求而且能用TasksAPI來關閉或者獲得一個Task的狀態並將其返回。。Elasticsearch還將建立此任務的記錄,做爲.tasks/task/${taskId}的文檔。保留和刪除由你抉擇。當您完成它或者刪除它時,Elasticsearch能夠回收它使用的空間。

wait_for_active_shards 在進行從新索引以前,一個碎片必須有多少個副本處於活動狀態。點擊此處查看更多。timeout控制每一個寫請求等待不可用碎片編程可用的時間。這兩種方法在BulkAPI中的工做方式徹底相同。因爲從新索引使用滾動搜索,您還能夠指定滾動參數來控制「search context」保持活動的時間(例如?scroll=10m)。默認值爲5m。

requests_per_second能夠被設置爲十進制的正數(1.4, 6, 1000, 等.) ,限制_reindex發出批量索引操做的速率。服務節流能夠將 requests_per_second 設置爲 -1.

節流是經過在批之間等待來完成的,這樣就能夠給_reindex內部使用的滾動設置一個考慮填充的超時。填充時間是batchs size除以requests_per_second和寫入時間之間的差額。默認狀況下batch size爲1000,因此若是requests_per_second被設置爲500:

target_time = 1000 / 500 per second = 2 seconds
`padding time` = target_time - write_time = 2 seconds - .5 seconds = 1.5 seconds
複製代碼

由於batch是做爲一個單獨的_bulk請求發出的,大的batch size將致使Elasticsearch建立許多請求而且等一段時間纔會開始下一組。這是間歇性的的而不是平滑的,這個默認值爲-1

響應體

JSON響應看起來像下面這樣:

{
  "took": 639,
  "timed_out": false,
  "total": 5,
  "updated": 0,
  "created": 5,
  "deleted": 0,
  "batches": 1,
  "noops": 0,
  "version_conflicts": 2,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": 1,
  "throttled_until_millis": 0,
  "failures": [ ]
}
複製代碼

took

​ 整個操做花費的總時長。

time_out

​ 若是在從新索引期間執行的任何請求超時,則將此標誌設置爲true。

total

​ 成功處理的文檔總數。

updated

​ 成功更新的文檔總數。

created

​ 成功建立的文檔總數。

deleted

​ 成功刪除的文檔總數。

batches

​ 經過reindex滾動請求拉回的數量

noops

​ 被忽略的文檔數。由於用於從新索引的腳本爲ctx.op返回了一個noop值。

version_conflicts

​ reindex命中的版本衝突數。

retries

​ reindex重試也沒有成功的數量。bulk是bulk動做重試的數量,search是search動做重試的數量。

throttled_millis

​ 請求休眠以符合requests_per_second的毫秒數。

requests_per_second

​ reindex期間請求每秒有效執行的次數。

throttled_until_millis

​ 在_reindex這個字段應該一直等於0,它僅僅意味着,當使用TaskAPI,它指示下一次(從epoch開始以毫秒爲單位)將再次執行節流請求,以符合requests_per_second

failures

​ 若是流程中存在任何不可恢復的錯誤,則會出現一系列故障。若是這不是空的,那麼請求就會由於這些失敗而停止。Reindex是使用batch實現的,任何失敗都會致使整個進程停止,可是當前batch中的全部失敗都會收集到數組中。您可使用conflicts選項來防止reindex在版本衝突上停止。

使用TaskAPI

你可使用TaskAPI來獲取全部正在運行中的reindex請求的狀態。

響應結果以下:

{
  "nodes" : {
    "r1A2WoRbTwKZ516z6NEs5A" : {
      "name" : "r1A2WoR",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "attributes" : {
        "testattr" : "test",
        "portsfile" : "true"
      },
      "tasks" : {
        "r1A2WoRbTwKZ516z6NEs5A:36619" : {
          "node" : "r1A2WoRbTwKZ516z6NEs5A",
          "id" : 36619,
          "type" : "transport",
          "action" : "indices:data/write/reindex",
            #這個對象包含了真正的狀態,它與響應JSON相同,只是添加了重要的total字段。total是_reindex但願執行的操做總數。您能夠經過添加updated、created的和deleted的字段來估計進度。當它們的和等於整個字段時,請求將結束。
          "status" : {    
            "total" : 6154,
            "updated" : 3500,
            "created" : 0,
            "deleted" : 0,
            "batches" : 4,
            "version_conflicts" : 0,
            "noops" : 0,
            "retries": {
              "bulk": 0,
              "search": 0
            },
            "throttled_millis": 0,
            "requests_per_second": -1,
            "throttled_until_millis": 0
          },
          "description" : "",
          "start_time_in_millis": 1535149899665,
          "running_time_in_nanos": 5926916792,
          "cancellable": true,
          "headers": {}
        }
      }
    }
  }
}
複製代碼

能夠經過Task id來直接查看Task,下面的例子展現了取回taskid爲r1A2WoRbTwKZ516z6NEs5A:36619:的信息:

curl -X GET "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619"
複製代碼

這個API的優點是集成了wait_for_completion=false而且返回了完成任務的狀態,若是task已經完成,而且 wait_for_completion=false,它將返回一個results或者error字段。這個特性的代價是wait_for_completion=false.tasks/task/${taskId}處建立的文檔。你能夠本身決定是否刪除。

使用Cancel Task API

任何Reindex都能被Task Calcel API取消。例如:

curl -X POST "localhost:9200/_tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel"
複製代碼

TaskId可使用TaskAPI來查到。

取消應該是在瞬間完成的,可是有可能會須要短暫的幾秒。Task API將跳過列出任務,直到它醒來自動取消。

Rethrottling(從新設置節流時長)

在運行reindex期間可使用_rethrottleAPI來改變requests_per_second 的值。

curl -X POST "localhost:9200/_reindex/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1"
複製代碼

TaskId可使用TaskAPI來查到。

就像在Reindex API上同樣設置,requests_per_second 值能被設置成-1來禁用節流或者設置成任何正數來節流。Rethrottling 加快查詢當即生效的速度,可是它減慢查詢在完成當前批處理後生效的速度。這將防止滾動超時。

Reindex來改變字段名

_reindex可用於構建具備重命名字段的索引的副本。假設您建立了一個包含以下文檔的索引:

curl -X POST "localhost:9200/test/_doc/1?refresh" -H 'Content-Type: application/json' -d'
{
  "text": "words words",
  "flag": "foo"
}
'
複製代碼

可是你不喜歡flag這個名字,想把flag替換爲tag。_reindex能幫你建立另外一個索引:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "test"
  },
  "dest": {
    "index": "test2"
  },
  "script": {
    "source": "ctx._source.tag = ctx._source.remove(\"flag\")"
  }
}
'
複製代碼

如今從新獲取文檔:

curl -X GET "localhost:9200/test2/_doc/1"
複製代碼

返回結果:

{
  "found": true,
  "_id": "1",
  "_index": "test2",
  "_type": "_doc",
  "_version": 1,
  "_seq_no": 44,
  "_primary_term": 1,
  "_source": {
    "text": "words words",
    "tag": "foo"
  }
}
複製代碼
切分

Reindex支持切片滾動,以並行化從新索引過程。這種並行化能夠提升效率,並提供一種方便的方法將請求分解爲更小的部分。

手動切分

對每一個請求經過提供一個slice id和切分總數來手動切分Reindex請求:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter",
    "slice": {
      "id": 0,
      "max": 2
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter",
    "slice": {
      "id": 1,
      "max": 2
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

若是你想驗證結果:

curl -X GET "localhost:9200/_refresh"
curl -X POST "localhost:9200/new_twitter/_search?size=0&filter_path=hits.total"
複製代碼

結果是這樣一個合理的total:

{
  "hits": {
    "total" : {
        "value": 120,
        "relation": "eq"
    }
  }
}
複製代碼

自動切分

您還可讓_reindex使用切片滾動自動並行化_uid上的切片。使用slices指定要使用的片數:

curl -X POST "localhost:9200/_reindex?slices=5&refresh" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}
'
複製代碼

你能夠驗證其結果:

curl -X POST "localhost:9200/new_twitter/_search?size=0&filter_path=hits.total"
複製代碼

結果是這樣一個合理的total:

{
  "hits": {
    "total" : {
        "value": 120,
        "relation": "eq"
    }
  }
}
複製代碼

設置slicesauto,Elasticsearch將自動的選擇一個合理的切分數來使用,此設置將在必定限度內使用每一個切塊一個切分。若是有多個源索引,它將根據分片數量最少的索引選擇切片的數量。

slices添加到_reindex只是自動執行上一節中使用的手動過程,建立子請求,這意味着它有一些奇怪的地方:

  • 你能夠在TaskAPI中看到這些請求。這些子請求是帶有slices請求的Task的childTask

  • 爲帶有slices的請求獲取任務狀態,只包含已完成slices的狀態。

  • 這些子請求能夠單獨尋址,用於cancelation(取消) 和rethrottling(改變節流的值)等操做。

  • 帶有slices的Rethrottling請求將按比例rethrottle未完成的子請求。

  • 關閉帶有slices的請求將關閉每一個子請求。

  • 因爲切片的性質,每一個子請求不會徹底獲得文檔部分。全部文檔都將被處理,可是有些部分可能比其餘部分更大。指望更大的slices具備更均勻的分佈。

  • 帶有slices的請求上的requests_per_secondsize等參數按比例分佈到每一個子請求。將這一點與上面關於分佈不均勻的觀點結合起來,咱們得出結論:使用帶slicessize可能不會致使reindex精確大小的文檔

  • 每一個子請求都得到稍微不一樣的源索引的快照,儘管這些快照幾乎是同時獲取的。

帶有slices的數量

若是是自動切分請求,設置slicesauto將選擇一個合理的數值來給大多數索引。若是手動切片或以其餘方式調優自動切片,請繼續閱讀下方內容:

slices數等於分片數這時候查詢性能是最好的。若是slices值很大,選擇一個更小的值會有損性能。將slices的數量設置爲大於分片片的數量一般不會提升效率,並且會增長開銷。

索引性能隨着分片的數量在可用資源之間線性擴展。

查詢或索引性能是否主導運行時取決於reindex的文檔和集羣資源。

同時Reindex索引

若是你有多個索引要Reindex,一般更好的作法是一次Reindex一個,而不是使用全局模式同時獲取多個。這樣,若是有任何錯誤,您能夠刪除部分完成的索引並從該索引從新開始,從而恢復該過程。它還使並行化過程變得至關簡單:將索引列表拆分爲reindex並並行運行每一個列表。

一次性bash腳本彷佛很好地解決了這個問題:

for index in i1 i2 i3 i4 i5; do
  curl -HContent-Type:application/json -XPOST localhost:9200/_reindex?pretty -d'{
    "source": {
      "index": "'$index'"
    },
    "dest": {
      "index": "'$index'-reindexed"
    }
  }'
done
複製代碼
Reindex daily索引

儘管有上面的建議,你可使用_reindex結合Painless來reindex daily 索引將新模板應用於現有文檔。

假設你有一下文件組成的索引:

curl -X PUT "localhost:9200/metricbeat-2016.05.30/_doc/1?refresh" -H 'Content-Type: application/json' -d'
{"system.cpu.idle.pct": 0.908}
'
curl -X PUT "localhost:9200/metricbeat-2016.05.31/_doc/1?refresh" -H 'Content-Type: application/json' -d'
{"system.cpu.idle.pct": 0.105}
'
複製代碼

metricbeat-*索引的新模板已經加載到Elasticsearch中,但它只適用於新建立的索引。Painless可用於reindex現有文檔並應用新模板。

下面的腳本從索引名稱中提取日期,並建立一個附加了-1的新索引。 來自metricbeat-2016.05.31的全部數據將reindex到metricbeat-2016.05.31-1

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "source": {
    "index": "metricbeat-*"
  },
  "dest": {
    "index": "metricbeat"
  },
  "script": {
    "lang": "painless",
    "source": "ctx._index = \u0027metricbeat-\u0027 + (ctx._index.substring(\u0027metricbeat-\u0027.length(), ctx._index.length())) + \u0027-1\u0027"
  }
}
'
複製代碼

從metricbeat 索引以前的全部文檔如今均可以在*-1中找到:

curl -X GET "localhost:9200/metricbeat-2016.05.30-1/_doc/1"
curl -X GET "localhost:9200/metricbeat-2016.05.31-1/_doc/1"
複製代碼

前一種方法還能夠與更改字段名稱結合使用,以便僅將現有數據加載到新索引中,並在須要時重命名任何字段。

獲取索引的隨機子集

_reindex可用於提取索引的隨機子集進行測試:

curl -X POST "localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
  "size": 10,
  "source": {
    "index": "twitter",
    "query": {
      "function_score" : {
        "query" : { "match_all": {} },
        "random_score" : {}
      }
    },
    #_reindex默認按_doc排序,所以random_score不會有任何效果,除非您覆蓋sort to _score。
    "sort": "_score"    
  },
  "dest": {
    "index": "random_twitter"
  }
}
'
複製代碼

Term Vectors

返回特定文檔字段中術語的信息和統計信息。文檔能夠存儲在索引中,也能夠由用戶人工提供。默認狀況下,術語向量是實時的,而不是接近實時的。這能夠經過將realtime參數設置爲false來更改。

curl -X GET "localhost:9200/twitter/_termvectors/1"
複製代碼

您能夠選擇使用url中的參數指定檢索信息的字段:

curl -X GET "localhost:9200/twitter/_termvectors/1?fields=message"
複製代碼

或者在請求體中添加請求字段,字段也可使用通配符指定,方法相似於multi match query

返回值

可請求的三種類型的值:term information, term statistics 和 field statistics,默認的,返回term information, 和 field statistics的全部字段信息,可是不返回term statistics 信息。

Term information

  • term frequency in the field (老是返回)
  • term positions (positions : true)
  • start and end offsets (offsets : true)
  • term payloads (payloads : true), as base64 encoded bytes

若是在索引中請求信息沒有存儲,若是可能的話,它將被實時計算。另外,能夠計算甚至不存在於索引中的文檔,而是由用戶提供的 term vectors。

開始和結束偏移量假設使用的是UTF-16編碼。若是您想使用這些偏移量來得到生成此令牌的原始文本,則應該確保您正在獲取的子字符串也使用UTF-16編碼。

Term statistics

設置 term_statisticstrue (默認爲false) 將會返回相關信息

  • total term frequency (一個term在全部文檔中出現的頻率是多少)
  • document frequency (包含當前term的文檔數量)

默認狀況下,那些值是不會返回的,由於term statistics對性能有嚴重影響

Field statistics

設置 term_statisticsfalse(默認爲true) 將會不會被返回

  • document count (包含當前字段有多少文檔)
  • sum of document frequencies (此字段中全部term的文檔頻率總和)
  • sum of total term frequencies (該字段中每一個項的總term頻率之和)

Term過濾

使用參數filter,還能夠根據tf-idf分數對返回的term進行篩選。

支持下列子參數:

max_num_terms 每一個字段必須返回的最大term數. 默認爲2525.
min_term_freq 忽略源文檔中小於此頻率的單詞. 默認爲1.
max_term_freq 忽略源文檔中小於此頻率的單詞. 默認爲無限制。
min_doc_freq 忽略至少在這麼多文檔中沒有出現的術語. 默認爲 1.
max_doc_freq 忽略出如今不少文檔中的單詞.默認爲無限制。
min_word_length 將被忽略的單詞的最小單詞長度.默認爲 0.
max_word_length 超過該長度的單詞將被忽略. 默認爲無限制 (0).
表現

Term和字段統計是不許確的。刪除的文檔不考慮在內,僅爲所請求的文檔所在的切分檢索信息。所以,term和字段統計僅做爲相對的度量有用,而絕對值在這方面沒有意義。默認狀況下,在請求人工文檔的term vectors時,隨機選擇一個分片來獲取統計信息。使用路由只會命中特定的分片。

返回存儲的term vectors

首先咱們存儲建立一個索引來存儲term vectors ,請求體以下:

curl -X PUT "localhost:9200/twitter" -H 'Content-Type: application/json' -d'
{ "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "term_vector": "with_positions_offsets_payloads",
        "store" : true,
        "analyzer" : "fulltext_analyzer"
       },
       "fullname": {
        "type": "text",
        "term_vector": "with_positions_offsets_payloads",
        "analyzer" : "fulltext_analyzer"
      }
    }
  },
  "settings" : {
    "index" : {
      "number_of_shards" : 1,
      "number_of_replicas" : 0
    },
    "analysis": {
      "analyzer": {
        "fulltext_analyzer": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "type_as_payload"
          ]
        }
      }
    }
  }
}
'
複製代碼

第二步,咱們添加一些文檔:

curl -X PUT "localhost:9200/twitter/_doc/1" -H 'Content-Type: application/json' -d'
{
  "fullname" : "John Doe",
  "text" : "twitter test test test "
}
'
curl -X PUT "localhost:9200/twitter/_doc/2" -H 'Content-Type: application/json' -d'
{
  "fullname" : "Jane Doe",
  "text" : "Another twitter test ..."
}
'
複製代碼

下面的請求返回關於text字段在文檔1中的全部信息和統計:

curl -X GET "localhost:9200/twitter/_termvectors/1" -H 'Content-Type: application/json' -d'
{
  "fields" : ["text"],
  "offsets" : true,
  "payloads" : true,
  "positions" : true,
  "term_statistics" : true,
  "field_statistics" : true
}
'
複製代碼

響應:

{
    "_id": "1",
    "_index": "twitter",
    "_type": "_doc",
    "_version": 1,
    "found": true,
    "took": 6,
    "term_vectors": {
        "text": {
            "field_statistics": {
                "doc_count": 2,
                "sum_doc_freq": 6,
                "sum_ttf": 8
            },
            "terms": {
                "test": {
                    "doc_freq": 2,
                    "term_freq": 3,
                    "tokens": [
                        {
                            "end_offset": 12,
                            "payload": "d29yZA==",
                            "position": 1,
                            "start_offset": 8
                        },
                        {
                            "end_offset": 17,
                            "payload": "d29yZA==",
                            "position": 2,
                            "start_offset": 13
                        },
                        {
                            "end_offset": 22,
                            "payload": "d29yZA==",
                            "position": 3,
                            "start_offset": 18
                        }
                    ],
                    "ttf": 4
                },
                "twitter": {
                    "doc_freq": 2,
                    "term_freq": 1,
                    "tokens": [
                        {
                            "end_offset": 7,
                            "payload": "d29yZA==",
                            "position": 0,
                            "start_offset": 0
                        }
                    ],
                    "ttf": 2
                }
            }
        }
    }
}
複製代碼

動態生成term vectors

沒有顯式存儲在索引中的Term vectors將自動動態計算。下面的請求返回文檔1中字段的全部信息和統計信息,即便這些term沒有顯式地存儲在索引中。注意,對於字段text,不從新生成term。

curl -X GET "localhost:9200/twitter/_termvectors/1" -H 'Content-Type: application/json' -d'
{
  "fields" : ["text", "some_field_without_term_vectors"],
  "offsets" : true,
  "positions" : true,
  "term_statistics" : true,
  "field_statistics" : true
}
'
複製代碼

人工文檔

還能夠爲人工文檔生成term vectors,即索引中不存在的文檔。例如,下面的請求將返回與示例1相同的結果。使用的映射由索引決定。

若是打開動態映射(默認),將動態建立原始映射中沒有的文檔字段。

curl -X GET "localhost:9200/twitter/_termvectors" -H 'Content-Type: application/json' -d'
{
  "doc" : {
    "fullname" : "John Doe",
    "text" : "twitter test test test"
  }
}
'
複製代碼

Per-feild 分析器

此外,可使用per_field_analyzer參數提供不一樣於字段的分析器。這對於以任何方式生成term vectors都頗有用,特別是在使用人工文檔時。當爲已經存儲term vectors的字段提供分析器時,將從新生成term vectors。

curl -X GET "localhost:9200/twitter/_termvectors" -H 'Content-Type: application/json' -d'
{
  "doc" : {
    "fullname" : "John Doe",
    "text" : "twitter test test test"
  },
  "fields": ["fullname"],
  "per_field_analyzer" : {
    "fullname": "keyword"
  }
}
'
複製代碼
{
  "_index": "twitter",
  "_type": "_doc",
  "_version": 0,
  "found": true,
  "took": 6,
  "term_vectors": {
    "fullname": {
       "field_statistics": {
          "sum_doc_freq": 2,
          "doc_count": 4,
          "sum_ttf": 4
       },
       "terms": {
          "John Doe": {
             "term_freq": 1,
             "tokens": [
                {
                   "position": 0,
                   "start_offset": 0,
                   "end_offset": 8
                }
             ]
          }
       }
    }
  }
}
複製代碼

Term 過濾

最後,返回的term能夠根據tf-idf分數進行篩選。在下面的示例中,咱們從具備給定「plot」字段值的人工文檔中得到三個最「interesting」的關鍵字。注意,關鍵字「Tony」或任何中止詞都不是響應的一部分,由於它們的tf-idf必須過低。

curl -X GET "localhost:9200/imdb/_termvectors" -H 'Content-Type: application/json' -d'
{
    "doc": {
      "plot": "When wealthy industrialist Tony Stark is forced to build an armored suit after a life-threatening incident, he ultimately decides to use its technology to fight against evil."
    },
    "term_statistics" : true,
    "field_statistics" : true,
    "positions": false,
    "offsets": false,
    "filter" : {
      "max_num_terms" : 3,
      "min_term_freq" : 1,
      "min_doc_freq" : 1
    }
}
'
複製代碼
{
   "_index": "imdb",
   "_type": "_doc",
   "_version": 0,
   "found": true,
   "term_vectors": {
      "plot": {
         "field_statistics": {
            "sum_doc_freq": 3384269,
            "doc_count": 176214,
            "sum_ttf": 3753460
         },
         "terms": {
            "armored": {
               "doc_freq": 27,
               "ttf": 27,
               "term_freq": 1,
               "score": 9.74725
            },
            "industrialist": {
               "doc_freq": 88,
               "ttf": 88,
               "term_freq": 1,
               "score": 8.590818
            },
            "stark": {
               "doc_freq": 44,
               "ttf": 47,
               "term_freq": 1,
               "score": 9.272792
            }
         }
      }
   }
}	
複製代碼

Multi termvectors API

Multi termvector API容許同時得到多個termvector。檢索termvectors的文檔由索引和id指定。可是也能夠在請求自己中人爲地提供這些文檔。

響應包括一個文檔數組,其中包含全部獲取的termvector,每一個元素都具備termvectors API提供的結構。舉個例子:

curl -X POST "localhost:9200/_mtermvectors" -H 'Content-Type: application/json' -d'
{
   "docs": [
      {
         "_index": "twitter",
         "_id": "2",
         "term_statistics": true
      },
      {
         "_index": "twitter",
         "_id": "1",
         "fields": [
            "message"
         ]
      }
   ]
}
'
複製代碼

有關可能的參數的描述,請參見[termvectors API](#Term Vectors)。

_mtermvector路徑也能夠用於索引(在這種狀況下,在body中不須要它):

curl -X POST "localhost:9200/twitter/_mtermvectors" -H 'Content-Type: application/json' -d'
{
   "docs": [
      {
         "_id": "2",
         "fields": [
            "message"
         ],
         "term_statistics": true
      },
      {
         "_id": "1"
      }
   ]
}
'
複製代碼

若是全部的文檔在相同的索引,而且參數也相同,請求能夠被簡化:

curl -X POST "localhost:9200/twitter/_mtermvectors" -H 'Content-Type: application/json' -d'
{
    "ids" : ["1", "2"],
    "parameters": {
    	"fields": [
         	"message"
      	],
      	"term_statistics": true
    }
}
'
複製代碼

另外,就和termvectors API同樣,能夠爲用戶提供的文檔生成termvectors。使用的映射由_index肯定。

curl -X POST "localhost:9200/_mtermvectors" -H 'Content-Type: application/json' -d'
{
   "docs": [
      {
         "_index": "twitter",
         "doc" : {
            "user" : "John Doe",
            "message" : "twitter test test test"
         }
      },
      {
         "_index": "twitter",
         "doc" : {
           "user" : "Jane Doe",
           "message" : "Another twitter test ..."
         }
      }
   ]
}
'
複製代碼

?refresh

當此請求所作的更改對搜索可見時,Index,Update,Delete,Bulk API支持設置refrash來控制。這些是容許的值:

空字符串或者true

​ 在操做發生後當即刷新相關的主分片和副本分片(而不是整個索引),以便更新後的文檔當即出如今搜索結果中。只有在確保它不會致使性能低下(不管是從索引仍是搜索的角度)以後,才應該這樣作。

wait_for

​ 在響應以前,等待請求所作的更改被刷新爲可見。這並不強制當即刷新,而是等待刷新發生。Elasticsearch自動刷新已更改每一個索引的分片。refresh_interval,默認值爲1秒。該設置是動態的。在任何支持刷新的API上調用Refresh API或將Refresh設置爲true也會致使刷新,從而致使已經運行的帶有Refresh =wait_for的請求返回。

false(默認值)

​ 不採起刷新相關操做。此請求所作的更改將在請求返回後的某個時刻變得可見。

選擇要使用的設置

除非你有更好的理由使用等待改變爲可見,不然使用refresh=false。或者,由於這是缺省值,因此將refresh參數保留在URL以外。這是最簡單和最快的選擇。

若是您絕對必須使請求所作的更改與請求同步可見,那麼您必須在向Elasticsearch添加更多負載(true)和等待響應更長的時間(wait_for)之間進行選擇。如下幾點應有助於做出這一決定:

  • 與true相比,對索引進行的更改越多,wait_for保存的工做就越多。在每一個索引只更改一次索引的狀況下。refresh_interval則不保存任何工做。
  • true建立效率較低的索引構造(小段),這些構造稍後必須合併爲更高效的索引構造(更大的段)。這意味着true的代價是在index時建立小段,在search時搜索小段,在merge時生成更大的段。
  • 永遠不要在一行中啓動多個refresh=wait_for請求。相反,使用refresh=wait_for將它們批處理爲單個批量請求,而Elasticsearch將並行地啓動它們,只有當它們所有完成時才返回。
  • 若是刷新間隔設置爲-1,禁用自動刷新,那麼refresh=wait_for的請求將無限期等待,直到某個操做致使刷新。相反,設置索引。refresh_interval小於默認值(如200ms)將使refresh=wait_for更快地返回,但它仍然會生成效率低下的segments。
  • refresh=wait_for隻影響正在運行的請求,可是,經過強制當即刷新,refresh=true將影響其餘正在進行的請求。一般,若是您有一個正在運行的系統,您不但願干擾它,那麼refresh=wait_for是一個較小的修改。
refrash=wait_for能夠強制刷新

當已經有索引時,若是出現refresh=wait_for請求。max_refresh_listener(默認值爲1000)請求等待對該分片的刷新,而後該請求的行爲將與將refresh設置爲true同樣:它將強制刷新。換言之:當refresh=wait_for請求返回時,它的更改對於搜索是可見的,同時防止對阻塞的請求使用未檢查的資源。若是一個請求由於耗盡了偵聽器插槽而強制刷新,那麼它的響應將包含「forced_refresh」:true。

不管修改切分多少次,批量請求在每一個切分上只佔用一個插槽。

例子

這些將建立一個文檔,並當即刷新索引,使其可見:

curl -X PUT "localhost:9200/test/_doc/1?refresh" -H 'Content-Type: application/json' -d'
{"test": "test"}
'
curl -X PUT "localhost:9200/test/_doc/2?refresh=true" -H 'Content-Type: application/json' -d'
{"test": "test"}
'
複製代碼

這將建立一個文檔,而不作任何事情,使其搜索可見:

curl -X PUT "localhost:9200/test/_doc/3" -H 'Content-Type: application/json' -d'
{"test": "test"}
'
curl -X PUT "localhost:9200/test/_doc/4?refresh=false" -H 'Content-Type: application/json' -d'
{"test": "test"}
'
複製代碼

這將建立一個文檔,並等待它成爲可見的搜索:

curl -X PUT "localhost:9200/test/_doc/4?refresh=wait_for" -H 'Content-Type: application/json' -d'
{"test": "test"}
'
複製代碼

樂觀併發控制

Elasticsearch是分佈式的,當文檔被建立,刪除,更新,更改,一個新的文檔版本就必須被複制到其餘節點。Elasticsearch是異步的,併發的,這意味着那些複製請求是併發的被髮送出去的,可能不按順序到達目的地,elasticsearch須要一種方法開確保老的文檔版本號永遠不會覆蓋新的文檔版本號。

爲了確保老的版本號永遠不會覆蓋新的版本號,對文檔執行的每一個操做都會經過主分片分配一個序列號,改序列號將會協調更改。每一個操做的序列號是自增的,而且較新的操做保證具備比舊操做更高的序列號。

例如,下面的索引命令將建立一個文檔,併爲其分配一個初始序列號和主term:

curl -X PUT "localhost:9200/products/_doc/1567" -H 'Content-Type: application/json' -d'
{
    "product" : "r2d2",
    "details" : "A resourceful astromech droid"
}
'
複製代碼

您能夠在響應的_seq_no_primary_term字段中看到分配的序列號和主term:

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 1
    },
    "_index" : "products",
    "_type" : "_doc",
    "_id" : "1567",
    "_version" : 1,
    "_seq_no" : 362,
    "_primary_term" : 2,
    "result" : "created"
}
複製代碼

Elasticsearch跟蹤要更改其存儲的每一個文檔的最後一個操做的序號和主term。在GET API的響應中,在_seq_no_primary_term字段中返回序列號和主項:

curl -X GET "localhost:9200/products/_doc/1567"
複製代碼

返回的結果:

{
    "_index" : "products",
    "_type" : "_doc",
    "_id" : "1567",
    "_version" : 1,
    "_seq_no" : 362,
    "_primary_term" : 2,
    "found": true,
    "_source" : {
        "product" : "r2d2",
        "details" : "A resourceful astromech droid"
    }
}
複製代碼

注意:經過設置seq_no_primary_term參數,搜索API能夠爲每次搜索命中返回_seq_no_primary_term

序列號和主term唯一地標識更改。經過記錄返回的序列號和主term,您能夠確保只在檢索後沒有對文檔進行其餘更改的狀況下更改文檔。這是經過設置索引API或刪除API的if_seq_noif_primary_term參數來實現的。

例如,下面的索引調用將確保向文檔添加一個標籤,而不會丟失對描述的任何潛在更改,或由另外一個API添加另外一個標籤:

curl -X PUT "localhost:9200/products/_doc/1567?if_seq_no=362&if_primary_term=2" -H 'Content-Type: application/json' -d'
{
    "product" : "r2d2",
    "details" : "A resourceful astromech droid",
    "tags": ["droid"]
}
'
複製代碼
相關文章
相關標籤/搜索