1. 程式人生 > >elasticsearch6.x官方文件學習筆記----Document API翻譯

elasticsearch6.x官方文件學習筆記----Document API翻譯

開始之前先學習

副本

        介紹:Elasticsearch的每個索引都被分成shard ,每個shard 可以有多個副本。這些副本稱為複製組,在新增或刪除文件時必須保持同步。如果我們不這樣做,從一個副本閱讀將會導致與從另一個副本閱讀非常不同的結果。保持碎片副本同步並提供從中讀取的過程稱為資料複製模型。

       Elasticsearch的資料複製模型基於主備份模型。該模型基於複製組中作為主shard 的一個副本。其他的副本稱為複製shard 。主索引作為所有索引操作的主要入口點。它負責驗證它們並確保它們是正確的。一旦主操作接受了索引操作,主操作還負責將操作複製到其他副本。

       本節的目的是對Elasticsearch複製模型作一個高層次的概述,並討論它對讀寫操作之間的各種互動的影響。

基本寫操作原理

       Elasticsearch中的每個索引操作首先使用路由解析為一個複製組,通常基於文件ID。一旦確定了複製組,操作將在內部轉發到組的當前主shard 。主shard 負責驗證操作並將其轉發到其他副本。由於副本可以離線,主副本不需要複製到所有副本。相反,Elasticsearch維護應該接收操作的shard 副本列表。這個列表稱為同步副本,由主節點維護。顧名思義,這些是一組“好的”shard 副本,它們保證已經處理了所有已向用戶確認的索引和刪除操作。主程式負責維護這個不變數,因此必須將所有操作複製到這個集合中的每個副本。

主碎片遵循這個基本流程:

  1. 驗證傳入操作並如果結構無效的話會拒絕它(例如:有一個物件欄位,其中有一個數字不是預期的)
  2. 在本地執行操作,即索引或刪除相關文件。這還將驗證欄位的內容並在需要時拒絕(例如:在Lucene中索引關鍵字值太長)。
  3. 將操作轉發到當前同步副本集中的每個副本。如果有多個副本,則並行執行。
  4. 一旦所有副本都成功地執行了操作並響應了主副本,主副本就會確認對客戶機的請求已經成功完成。

故障處理

       在索引過程中,很多事情都可能出錯——磁碟可能損壞,節點可能彼此斷開連線,或者一些配置錯誤可能會導致副本上的操作失敗,儘管主伺服器上的操作是成功的。這種情況並不常見,但主shard必須對其作出反應。

       在主節點本身失敗的情況下,主節點所在的節點將向主節點發送關於主節點的訊息。索引操作將等待(預設情況下最多1分鐘),以便主伺服器將一個副本提升為一個新的主副本。然後,操作將被轉發到新的主伺服器進行處理。注意,主節點還監視節點的健康狀況,並可能決定提前降級主節點。這通常發生在持有主節點的節點由於網路問題與叢集隔離時。

       在主伺服器上成功執行操作之後,主伺服器必須在副本碎片上執行操作時處理潛在的故障。這可能是由於副本上的實際故障,或由於網路問題阻止操作到達副本(或阻止副本響應)造成的。所有這些都具有相同的最終結果:同步複製集中的一個副本丟失了將要被確認的操作。為了避免違反不變數,主伺服器向主伺服器傳送一條訊息,請求從同步複製集中刪除有問題的碎片。主伺服器只有在刪除了碎片後才會確認操作。注意,主節點還將指示另一個節點開始構建一個新的碎片副本,以便將系統恢復到健康狀態。

       在將操作轉發到副本時,主伺服器將使用副本來驗證它仍然是活動的主伺服器。如果主伺服器由於網路分割槽(或長時間GC)而被隔離,在這之前它可能會繼續處理傳入的索引操作,直到意識到它已經降級了。來自過期主程式的操作將被副本拒絕。當主伺服器收到來自副本的拒絕請求的響應,因為它不再是主伺服器時,它會聯絡主伺服器,並知道它已經被替換了。然後將操作路由到新的主伺服器。

基本讀操作原理

       在Elasticsearch中讀取可以是非常輕量的查詢,也可以是繁重的搜尋請求,而複雜的聚合會佔用大量的CPU資源。主備份模型的優點之一是,它保持所有碎片副本相同(飛行操作除外)。因此,一個同步副本就足以服務於讀請求。

       當節點接收到讀請求時,該節點負責將其轉發到持有相關碎片的節點、整理響應和響應客戶機。我們將該節點稱為該請求的協調節點。基本流程如下:

  1. 將讀取請求解析到相關的碎片。注意,由於大多數搜尋將被髮送到一個或多個索引,它們通常需要從多個碎片中讀取,每個碎片代表資料的不同子集。
  2. 從碎片複製組中選擇每個相關碎片的活動副本。這可以是主副本,也可以是副本。預設情況下,Elasticsearch只會在碎片副本之間進行。
  3. 將碎片級別的讀取請求傳送到選中的副本。
  4. 將結果進行合併。注意,在get by ID查詢的情況下,只有一個切分是相關的,可以跳過這一步。

故障處理:

當碎片無法響應讀請求時,協調節點將從同一複製組中選擇另一個副本,並將碎片級搜尋請求傳送到該副本。重複的失敗會導致碎片副本不可用。在某些情況下,比如_search, Elasticsearch將更喜歡快速響應,儘管會得到部分結果,而不是等待問題得到解決(響應的_shards頭中顯示了部分結果)。

簡單介紹了副本,接下來就學習API了。

Index API

       首先是先介紹 mapping type, Mapping types will be completely removed in Elasticsearch 7.0.0.這是官網原話。我也不知道為啥要介紹mapping type,我是按照官網講的來的。

1)什麼是 mapping type:

       自從首次釋出Elasticsearch以來,每個文件都儲存在一個索引中,並分配一個對映型別。對映型別用於表示被索引的文件或實體的型別,例如twitter索引可能有user型別和tweet型別。

       每個對映型別都可以有自己的欄位,因此使用者型別可能有full_name欄位、user_name欄位和email欄位,而tweet型別可以有content欄位、tweeted_at欄位和使用者型別類似的user_name欄位。

每個文件都有一個包含型別名的_type元欄位,通過在URL中指定型別名,搜尋可以被限制為一個或多個型別:

GET twitter/user,tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

_type欄位與文件的_id合併生成_uid欄位,因此具有相同_id的不同型別的文件可以存在於單個索引中。

2)為什麼要移除mapping type?

      最初,我們討論了類似於SQL資料庫中的“資料庫”的“索引”,以及等效於“表”的“型別”。

      這是一個糟糕的類比,導致了錯誤的假設。在SQL資料庫中,表是相互獨立的。一個表中的列與另一個表中的同名列沒有關係。對於對映型別中的欄位,情況並非如此。換句話說,使用上面的示例,使用者型別中的user_name欄位儲存在與tweet型別中的user_name欄位完全相同的欄位中,並且兩個user_name欄位在兩種型別中都必須具有相同的對映(定義)。

       例如,當您想要刪除一個型別中的日期欄位和相同索引中的另一個型別中的布林欄位時,這可能會導致挫敗。最重要的是,儲存在同一索引中具有很少或沒有共同欄位的不同實體會導致資料稀疏,並妨礙Lucene高效壓縮文件的能力。基於這些原因,我們決定從Elasticsearch中刪除對映型別的概念。

3)mapping type的替代品

①給每個文件建立一個索引。

②自定義type欄位:

       當然,叢集中可以存在多少個主碎片是有限制的,因此您可能不希望浪費整個碎片來收集幾千個文件。在本例中,您可以實現自己的自定義型別欄位,該欄位的工作方式與舊_type類似。

       讓我們以上面的user/tweet示例為例。最初,工作流應該是這樣的:

PUT twitter
{
  "mappings": {
    "user": {
      "properties": {
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" }
      }
    },
    "tweet": {
      "properties": {
        "content": { "type": "text" },
        "user_name": { "type": "keyword" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/user/kimchy
{
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "[email protected]"
}

PUT twitter/tweet/1
{
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

您可以通過新增一個自定義型別欄位來實現相同的功能,如下所示:

PUT twitter
{
  "mappings": {
    "_doc": {
      "properties": {
        "type": { "type": "keyword" }, 
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" },
        "content": { "type": "text" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/_doc/user-kimchy
{
  "type": "user", 
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "[email protected]"
}

PUT twitter/_doc/tweet-1
{
  "type": "tweet", 
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "user_name": "kimchy"
        }
      },
      "filter": {
        "match": {
          "type": "tweet" 
        }
      }
    }
  }
}

顯式型別欄位取代了隱式_type欄位。

ok 前面說了一堆亂起八糟的東西。現在進入正題。

1)新增索引:

      索引API在特定索引中新增或更新型別化JSON文件,使其可搜尋。下面的示例將JSON文件插入到“twitter”索引中,其型別名為“_doc”,id為1:

curl -X PUT "localhost:9200/twitter/_doc/1"  -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

2)自動索引:

       索引操作自動建立索引,如果沒有之前建立,並自動建立一個動態型別對映為特定型別如果尚未建立。對映本身非常靈活,並且沒有模式。新的欄位和物件將自動新增到指定型別的對映定義中。

      Automatic index creation can be disabled by setting action.auto_create_index to false in the config file of all nodes. Automatic mapping creation can be disabled by settingindex.mapper.dynamic to false per-index as an index setting.

    Automatic index creation can include a pattern based white/black list, for example, set action.auto_create_index to +aaa*,-bbb*,+ccc*,-* (+ meaning allowed, and - meaning disallowed)。官方原話.如何設定自動索引。

3)版本:

沒看懂。

4)Opration   Type:

索引操作還接受op_type,可用於強制建立操作,允許“如果沒有”的行為。使用create時,如果該id文件已經存在於索引中,則索引操作將失敗。

下面是一個使用op_type引數的例子:

curl -X PUT "localhost:9200/twitter/_doc/1?op_type=create"  -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

指定create的另一個選項是使用以下uri:

curl -X PUT "localhost:9200/twitter/_doc/1/_create"  -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/"  -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"
}

路由:

預設情況下,碎片放置(或路由)是通過使用文件id值的雜湊來控制的。為了實現更明確的控制,可以使用路由引數直接在每個操作的基礎上指定路由器使用的雜湊函式的值。例如:

curl -X POST "localhost:9200/twitter/_doc?routing=kimchy"  -d'
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
'

在上面的示例中,“_doc”文件根據提供的路由引數“kimchy”被路由到一個碎片。

在設定顯式對映時,可以選擇使用_routing欄位指導索引操作,從文件本身提取路由值。這確實需要額外的文件解析傳遞的成本(非常低)。如果定義了_routing對映並設定為必需的,如果沒有提供或提取路由值,索引操作將失敗。

副本的分發:

索引操作根據其路由(請參閱上面的路由部分)定向到主碎片,並在包含此碎片的實際節點上執行。主碎片完成操作後,如果需要,更新將分發給適用的副本。

等待活躍的副本:

為了提高對系統的寫操作的彈性,可以將索引操作配置為在繼續操作之前等待一定數量的活動碎片副本。如果必需的碎片副本數量不可用,那麼寫操作必須等待並重試,直到必要的碎片副本啟動或超時。預設情況下,寫操作只等待主碎片處於活動狀態後再繼續(即wait_for_active_shards=1)。通過設定index.write.wait_for_active_shards,可以在索引設定中動態覆蓋此預設值。要更改每個操作的這種行為,可以使用wait_for_active_shards請求引數。

有效值是所有或任何正整數,直到索引中每個碎片的配置副本總數(即number_of_replicas+1)。指定一個負數或一個大於碎片副本數量的數字會丟擲錯誤。

例如,假設我們有一個由三個節點組成的叢集,a、B和C,我們建立了一個索引索引,將副本的數量設定為3(結果是4個碎片副本,比節點多一個副本)。如果我們嘗試索引操作,預設情況下,操作只會在繼續之前確保每個碎片的主副本可用。這意味著,即使B和C宕機,並且A託管主碎片副本,索引操作仍然只處理資料的一個副本。如果將wait_for_active_shards設定為3(所有3個節點都已啟動),那麼在繼續之前,索引操作將需要3個活動碎片副本,這一要求應該得到滿足,因為叢集中有3個活動節點,每個節點都持有碎片的副本。但是,如果我們將wait_for_active_shards設定為all(或4,這是相同的),索引操作將不會繼續,因為索引中沒有每個碎片的所有4個副本。除非叢集中出現一個新節點來承載碎片的第四個副本,否則操作將超時。

需要注意的是,這個設定大大減少了寫入操作不寫入到所需碎片副本數量的機會,但它並沒有完全排除這種可能性,因為這種檢查發生在寫入操作開始之前。一旦寫操作開始,複製仍然可能在任何數量的碎片副本上失敗,但在主副本上仍然成功。寫操作響應的_shards部分顯示覆製成功/失敗的碎片副本的數量。

{
    "_shards" : {
        "total" : 2,
        "failed" : 0,
        "successful" : 2
    }
}

控制元件何時該請求所做的更改對搜尋可見。 See refresh.

GET API

get API可以根據id從索引中獲取JSON型別的文件,下面的示例從名為twitter的索引中獲取JSON文件,該索引的型別為_doc, id值為0:

curl -X GET "localhost:9200/twitter/_doc/0"

上述get操作的結果為:

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

上面的結果包括我們希望檢索的文件的_index、_type、_id和_version,包括文件的實際內容_source(如響應中的found欄位所示)。

get的實時問題:

預設情況下,get API是實時的,不受索引的重新整理率的影響(當資料對搜尋可見時)。如果文件已經更新但尚未重新整理,則get API將發出一個就地重新整理呼叫,以使文件可見。這還將使自上次重新整理以來更改的其他文件可見。為了禁用realtime GET,可以將realtime引數設定為false。

Source 過濾:

預設情況下,get操作返回_source欄位的內容,除非使用了stored_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_include=*.id&_source_exclude=entities"

如果您只想指定include,則可以使用更短的符號:

curl -X GET "localhost:9200/twitter/_doc/0?_source=*.id,retweeted"

Stored Fields:

get操作允許指定一組儲存欄位,這些欄位將通過傳遞stored_fields引數返回。如果請求的欄位沒有設定為stored,它們將被忽略。例如,考慮以下對映:

curl -X PUT "localhost:9200/twitter"  -d'
{
   "mappings": {
      "_doc": {
         "properties": {
            "counter": {
               "type": "integer",
               "store": false
            },
            "tags": {
               "type": "keyword",
               "store": true
            }
         }
      }
   }
}
'

現在我們新增一篇文件:

curl -X PUT "localhost:9200/twitter/_doc/1"  -d'
{
    "counter" : 1,
    "tags" : ["red"]
}
'

get它:

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

返回結果為:

{
   "_index": "twitter",
   "_type": "_doc",
   "_id": "1",
   "_version": 1,
   "found": true,
   "fields": {
      "tags": [
         "red"
      ]
   }
}

從文件本身獲取的欄位值總是作為陣列返回。由於counter欄位不stored,所以get請求在嘗試獲取stored_fields時只會忽略它。

直接獲取_source:

通過如下方式:

curl -X GET "localhost:9200/twitter/_doc/1/_source"

您還可以使用相同的source過濾引數來控制_source的哪些部分將被返回:

curl -X GET "localhost:9200/twitter/_doc/1/_source?_source_include=*.id&_source_exclude=entities'"

副本偏愛:

可以控制用於在哪個碎片副本上執行get請求的首選項。預設情況下,操作在碎片副本之間隨機進行。

首選項可以設定為:

_primary

操作將只在主碎片上執行。

_local

如果可能的話,該操作更願意在本地分配的碎片上執行。

Custom(字串)值

將使用自定義值來確保相同的碎片將用於相同的自定義值。當在不同的重新整理狀態下敲擊不同的碎片時,這有助於“跳轉值”。示例值可以類似於web會話id或使用者名稱。

refresh:

可以將refresh引數設定為true,以便在get操作之前重新整理相關的碎片並使其可搜尋。在仔細考慮和驗證之後,應該將其設定為true,以確保不會對系統造成沉重的負載(並減慢索引速度)。

Delete API

跳過。

Delete By Query API

_delete_by_query的最簡單用法是對匹配查詢的每個文件執行刪除操作。以下是API:

curl -X POST "localhost:9200/twitter/_delete_by_query"  -d'
{
  "query": { 
    "match": {
      "message": "some message"
    }
  }
}
'

_delete_by_query在索引啟動時獲取一個快照,並使用內部版本控制刪除它找到的內容。這意味著,如果文件在快照獲取時間和刪除請求處理時間之間發生更改,就會出現版本衝突。當版本匹配時,文件將被刪除。

注意:由於內部版本控制不支援將值0作為有效的版本號,所以版本為0的文件不能使用_delete_by_query刪除,請求將失敗。

在_delete_by_query執行期間,將依次執行多個搜尋請求,以查詢要刪除的所有匹配文件。每次發現一批文件時,都會執行相應的批量請求來刪除所有這些文件。如果搜尋請求或批量請求被拒絕,_delete_by_query依賴預設策略重試被拒絕的請求(最多10次,以指數級後退)。達到最大重試限制會導致_delete_by_query中止,並在響應失敗時返回所有失敗。已經執行的刪除操作仍然有效。換句話說,程序不會回滾,只會中止。當第一個失敗導致中止時,失敗的批量請求返回的所有失敗都在failure元素中返回;因此,可能會有很多失敗的實體。

如果您希望統計版本衝突而不是導致它們中止,那麼在url上設定conflicts=proceed或請求體中的“conflicts”:“proceed”。

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

curl -X POST "localhost:9200/twitter/_doc/_delete_by_query?conflicts=proceed"  -d'
{
  "query": {
    "match_all": {}
  }
}
'

也可以同時刪除多個索引和多個型別的文件,就像搜尋API:

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

切片:

按查詢刪除支援切片滾動,以並行化刪除過程。這種並行化可以提高效率,並提供一種將請求分解為更小的部分的方便方法。

通過為每個請求提供片id和片的總數,手工地對每個查詢進行刪除:

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
      }
    }
  }
}
'

結果:

{
  "hits": {
    "total": 0
  }
}

自動切片:

您還可以使用切片滾動在_uid上切片,讓逐個查詢的刪除自動並行化。使用切片來指定要使用的切片數量:

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

Update API

update API允許基於提供的指令碼更新文件。該操作從索引中獲取文件(與碎片合併),執行指令碼(使用可選的指令碼語言和引數),並對結果進行索引(也允許刪除或忽略操作)。它使用版本控制來確保在“get”和“reindex”期間沒有發生更新。

注意,這個操作仍然意味著文件的完全重新索引,它只是刪除了一些網路往返,減少了get和索引之間版本衝突的機會。需要啟用_source欄位才能使該特性工作。

例如,讓我們索引一個簡單的文件:

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

指令碼更新:

現在,我們可以執行一個指令碼來增加counter:

curl -X POST "localhost:9200/test/_doc/1/_update"  -d'
{
    "script" : {
        "source": "ctx._source.counter += params.count",
        "lang": "painless",
        "params" : {
            "count" : 4
        }
    }
}
'

我們可以新增一個標籤到標籤列表(注意,如果標籤存在,它仍然會新增它,因為它是一個列表):

curl -X POST "localhost:9200/test/_doc/1/_update"  -d'
{
    "script" : {
        "source": "ctx._source.tags.add(params.tag)",
        "lang": "painless",
        "params" : {
            "tag" : "blue"
        }
    }
}
'

除了_source,通過ctx對映還可以使用以下變數:_index、_type、_id、_version、_routing和_now(當前時間戳)。

我們還可以在文件中新增一個新欄位:

curl -X POST "localhost:9200/test/_doc/1/_update"  -d'
{
    "script" : "ctx._source.new_field = \u0027value_of_new_field\u0027"
}
'

或者移除一個欄位:

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

我們甚至可以改變執行的操作。如果標籤欄位包含綠色,這個例子將刪除文件,否則什麼也不做:

curl -X POST "localhost:9200/test/_doc/1/_update"  -d'
{
    "script" : {
        "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = \u0027delete\u0027 } else { ctx.op = \u0027none\u0027 }",
        "lang": "painless",
        "params" : {
            "tag" : "green"
        }
    }
}
'

文件部分更新:

更新API還支援傳更新文件的一部分,這些文件將合併到現有文件中(簡單的遞迴合併、物件的內部合併、替換核心“鍵/值”和陣列)。要完全替換現有文件,應該使用索引API。以下部分更新為現有文件添加了一個新欄位:

curl -X POST "localhost:9200/test/_doc/1/_update"  -d'
{
    "doc" : {
        "name" : "new_name"
    }
}
'

通過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支援指令碼來更新文件:

curl -X POST "localhost:9200/twitter/_update_by_query" -d'
{
  "script": {
    "source": "ctx._source.likes++",
    "lang": "painless"
  },
  "query": {
    "term": {
      "user": "kimchy"
    }
  }
}
'

正如在更新API中可以設定ctx一樣。op更改執行的操作:

無操作

ctx設定。如果您的指令碼決定不需要做任何更改,op = "noop"。這會導致_update_by_query從其更新中忽略該文件。在響應體的noop計數器中不會報告此操作。

刪除

ctx設定。如果指令碼決定必須刪除文件,op =“delete”。刪除操作將在響應體中已刪除的計數器中報告。

設定ctx。操作到其他任何地方都是錯誤的。在ctx中設定任何其他欄位都是一個錯誤。

注意,我們不再指定conflicts=proceed。在這種情況下,我們希望版本衝突中止程序,以便能夠處理失敗。

這個API不允許您移動它所觸及的文件,只需修改它們的原始碼。這是故意的!我們沒有規定要把檔案從原來的位置移走。

Multi Get API

想要查詢的資料寫在doc陣列中,資料的結構跟GET API的一樣。

curl -X GET "localhost:9200/_mget"  -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'

mget端點還可以用於索引(在這種情況下,主體中不需要索引):

curl -X GET "localhost:9200/test/_mget"  -d'
{
    "docs" : [
        {
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
'

and type:

GET /test/type/_mget
{
    "docs" : [
        {
            "_id" : "1"
        },
        {
            "_id" : "2"
        }
    ]
}

在這種情況下,ids元素可以直接用於簡化請求:

curl -X GET "localhost:9200/test/type/_mget" -d'
{
    "ids" : ["1", "2"]
}
'

Source Filter:

具體用法跟 GetAPI類似:

curl -X GET "localhost:9200/_mget" -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"]
            }
        }
    ]
}
'

獲取欄位:

curl -X GET "localhost:9200/_mget"  -d'
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "stored_fields" : ["field1", "field2"]
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2",
            "stored_fields" : ["field3", "field4"]
        }
    ]
}
'

BULK API

如果要提供文字檔案輸入來進行curl,則必須使用——data-binary標誌,而不是普通的-d。後者不保留換行符。例子:

$ cat requests
{ "index" : { "_index" : "test", "_type" : "_doc", "_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}}]}

下面是一個正確的批量命令序列示例:

curl -X POST "localhost:9200/_bulk"  -d'
{ "index" : { "_index" : "test", "_type" : "_doc", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "_doc", "_id" : "2" } }
{ "create" : { "_index" : "test", "_type" : "_doc", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "_doc", "_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
         }
      }
   ]
}

Reindex API

重要:Reindex不會嘗試設定目標索引。它不復制源索引的設定。您應該在執行_reindex操作之前設定目標索引,包括設定對映、碎片計數、副本等。

_reindex的最基本形式只是將文件從一個索引複製到另一個索引。這將從twitter索引中複製文件到new_twitter索引中:

curl -X POST "localhost:9200/_reindex"  -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_query一樣,_reindex獲取源索引的快照,但是它的目標必須是不同的索引,因此不太可能發生版本衝突。dest元素可以配置為索引API來控制樂觀併發控制。僅僅省略version_type(如上所述)或將其設定為internal將導致Elasticsearch盲目地將文件轉儲到目標中,覆蓋碰巧具有相同型別和id的任何文件:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "internal"
  }
}
'

將version_type設定為external將導致Elasticsearch從源中儲存版本,建立丟失的文件,並更新目標索引中比源索引中版本更老的文件:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "external"
  }
}
'

設定要建立的op_type將導致_reindex只在目標索引中建立丟失的文件。所有現有文件都會導致版本衝突:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}
'

預設情況下,衝突會中止_reindex程序,但是您可以通過在請求體中設定“conflicts”:“proceed”來計算它們:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "conflicts": "proceed",
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}
'

可以通過向source中新增type或新增query來限制文件。這隻會把kimchy的tweets複製到new_twitter:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": "twitter",
    "type": "_doc",
    "query": {
      "term": {
        "user": "kimchy"
      }
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'

索引和輸入源都可以是列表,允許您在一個請求中複製許多源。這個例子將會從twitter和blog索引中的_doc和post型別中複製文件。對於更具體的引數,可以使用query。

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": ["twitter", "blog"],
    "type": ["_doc", "post"]
  },
  "dest": {
    "index": "all_together"
  }
}
'

還可以通過設定大小來限制已處理文件的數量。這將只從twitter複製一個文件到new_twitter:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "size": 1,
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}
'

如果您想從twitter索引中獲得一組特定的文件,您需要使用sort。排序使滾動效率降低,但在某些情況下,它是值得的。如果可能的話,選擇更有選擇性的查詢而不是大小和排序。這將從twitter複製10000個文件到new_twitter:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "size": 10000,
  "source": {
    "index": "twitter",
    "sort": { "date": "desc" }
  },
  "dest": {
    "index": "new_twitter"
  }
}
'

source部分支援搜尋請求中支援的所有元素。例如,只有原始文件中欄位的一個子集可以使用source過濾進行索引,如下所示:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "index": "twitter",
    "_source": ["user", "_doc"]
  },
  "dest": {
    "index": "new_twitter"
  }
}
'

與_update_by_query類似,_reindex支援修改文件的指令碼。與_update_by_query不同,指令碼可以修改文件的元資料。這個例子中提到了源文件的版本:

curl -X POST "localhost:9200/_reindex"  -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"。在響應體的noop計數器中不會報告此操作。

delete

ctx設定。如果指令碼決定必須從目標索引中刪除文件,op =“delete”。刪除操作將在響應體中已刪除的計數器中報告。

設定ctx。對任何其他欄位的op都將返回一個錯誤,就像在ctx中設定任何其他欄位一樣。

想想這些可能性吧!只是小心些而已。你可以改變:

  • _id
  • _type
  • _index
  • _version
  • _routing

遠端reindex:

curl -X POST "localhost:9200/_reindex"  -d'
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}
'

Trem Vectors

返回關於特定文件欄位中的術語的資訊和統計資訊。文件可以儲存在索引中,也可以由使用者人工提供。Term vectors預設情況下是實時的,而不是接近實時的。這可以通過將realtime引數設定為false來更改。

curl -X GET "localhost:9200/twitter/_doc/1/_termvectors"

可以選擇,您可以使用url中的引數指定檢索資訊的欄位:

curl -X GET "localhost:9200/twitter/_doc/1/_termvectors?fields=message"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

未完待續.......