ElasticSearch版本2.4.2,新版本有待學(xué)習(xí)
什么是文檔寄摆?
在大多數(shù)應(yīng)用中蒸眠,多數(shù)實(shí)體或?qū)ο罂梢员恍蛄谢癁榘I值對的Json對象,一個 *鍵* 可以是一個字段或字段名稱窿凤,一個 *值* 可以是一個object:
{
"name": "John Smith",
"age": 42,
"confirmed": true,
"join_date": "2014-06-01",
"home": {
"lat": 51.5,
"lon": 0.1
},
"accounts": [
{
"type": "facebook",
"id": "johnsmith"
},
{
"type": "twitter",
"id": "johnsmith"
}
]
}
通常情況下仅偎,我們使用的術(shù)語 對象 和 文檔 是可以互相替換的。不過雳殊,有一個區(qū)別: 一個對象僅僅是類似于 hash 橘沥、 hashmap 、字典或者關(guān)聯(lián)數(shù)組的 JSON 對象夯秃,對象中也可以嵌套其他的對象座咆。 對象可能包含了另外一些對象。在 Elasticsearch 中仓洼,術(shù)語 文檔 有著特定的含義介陶。它是指最頂層或者根對象, 這個根對象被序列化成 JSON 并存儲到 Elasticsearch 中,指定了唯一 ID色建。
字段名稱可以使用任何合法的字符串哺呜,不可以使用英文句號(.)
文檔元數(shù)據(jù)
一個文檔不單單包含本身的數(shù)據(jù),也包含一些元數(shù)據(jù)--有關(guān) *文檔* 本身的信息箕戳。三個必須的元數(shù)據(jù)如下:
_index:文檔存放在哪里
_type:文檔對象的類別
_id:文檔的唯一標(biāo)識
_index
一個 索引 應(yīng)該是因共同的特性被分組到一起的文檔集合某残。 例如,你可能存儲所有的產(chǎn)品在索引 products 中陵吸,而存儲所有銷售的交易到索引 sales 中玻墅。 雖然也允許存儲不相關(guān)的數(shù)據(jù)到一個索引中,但這通匙吵妫看作是一個反模式的做法澳厢。
實(shí)際上,在 Elasticsearch 中,我們的數(shù)據(jù)是被存儲和索引在 分片 中剩拢,而一個索引僅僅是邏輯上的命名空間线得, 這個命名空間由一個或者多個分片組合在一起。
然而裸扶,這是一個內(nèi)部細(xì)節(jié)框都,我們的應(yīng)用程序根本不應(yīng)該關(guān)心分片,對于應(yīng)用程序而言呵晨,只需知道文檔位于一個 索引 內(nèi)。 Elasticsearch 會處理所有的細(xì)節(jié)熬尺。
我們將在 索引管理 介紹如何自行創(chuàng)建和管理索引摸屠,但現(xiàn)在我們將讓 Elasticsearch 幫我們創(chuàng)建索引。 所有需要我們做的就是選擇一個索引名粱哼,這個名字必須小寫季二,不能以下劃線開頭,不能包含逗號揭措。我們用 website 作為索引名舉例胯舷。
_type
數(shù)據(jù)可能在索引中只是松散的組合在一起,但是通常明確定義一些數(shù)據(jù)中的子分區(qū)是很有用的绊含。 例如桑嘶,所有的產(chǎn)品都放在一個索引中,但是你有許多不同的產(chǎn)品類別躬充,比如 "electronics" 逃顶、 "kitchen" 和 "lawn-care"。
這些文檔共享一種相同的(或非常相似)的模式:他們有一個標(biāo)題充甚、描述以政、產(chǎn)品代碼和價格。他們只是正好屬于“產(chǎn)品”下的一些子類伴找。
Elasticsearch 公開了一個稱為 types (類型)的特性盈蛮,它允許您在索引中對數(shù)據(jù)進(jìn)行邏輯分區(qū)。不同 types 的文檔可能有不同的字段技矮,但最好能夠非常相似抖誉。 我們將在 類型和映射 中更多的討論關(guān)于 types 的一些應(yīng)用和限制。
_id
ID 是一個字符串穆役, 當(dāng)它和 _index 以及 _type 組合就可以唯一確定 Elasticsearch 中的一個文檔寸五。 當(dāng)你創(chuàng)建一個新的文檔,要么提供自己的 _id 耿币,要么讓 Elasticsearch 幫你生成梳杏。
其他有待編輯
索引文檔
通過使用 index API ,文檔可以被 索引 —— 存儲和使文檔可被搜索 。 但是首先十性,我們要確定文檔的位置叛溢。正如我們剛剛討論的,一個文檔的 _index 劲适、 _type 和 _id 唯一標(biāo)識一個文檔楷掉。 我們可以提供自定義的 _id 值,或者讓 index API 自動生成霞势。
- 如果你的文檔有一個自然的 標(biāo)識符 (例如烹植,一個 user_account 字段或其他標(biāo)識文檔的值),應(yīng)該使用這個值來做id
- 如果你的數(shù)據(jù)沒有自然的 ID愕贡, Elasticsearch 可以幫我們自動生成 ID 草雕。
自動生成ID 的 請求的結(jié)構(gòu)調(diào)整為: 不再使用 PUT 謂詞(“使用這個 URL 存儲這個文檔”), 而是使用 POST 謂詞(“存儲文檔在這個 URL 命名空間下”)固以。
現(xiàn)在該 URL 只需包含 _index 和 _type :
如 POST /website/blog/
自動生成的 ID 是 URL-safe墩虹、 基于 Base64 編碼且長度為20個字符的 GUID 字符串。 這些 GUID 字符串由可修改的 FlakeID 模式生成憨琳,這種模式允許多個節(jié)點(diǎn)并行生成唯一 ID 诫钓,且互相之間的沖突概率幾乎為零。
取回一個文檔
為了從 Elasticsearch 中檢索出文檔 篙螟,我們?nèi)匀皇褂孟嗤?_index , _type , 和 _id 菌湃,但是 HTTP 謂詞 更改為 GET :
GET /website/blog/123
有些文檔上說的pretty參數(shù),這是用于格式化輸出的闲擦,只是為了易讀慢味,一般插件都做了這個工作。
GET 請求的響應(yīng)體包括 {"found": true} 墅冷,這證實(shí)了文檔已經(jīng)被找到纯路。 如果我們請求一個不存在的文檔,我們?nèi)耘f會得到一個 JSON 響應(yīng)體寞忿,但是 found 將會是 false 驰唬。 此外, HTTP 響應(yīng)碼將會是 404 Not Found 腔彰,而不是 200 OK 叫编。
返回文檔中的一部分
默認(rèn)情況下, GET 請求 會返回整個文檔霹抛,這個文檔正如存儲在 _source 字段中的一樣搓逾。但是也許你只對其中的 title 字段感興趣。單個字段能用 _source 參數(shù)請求得到杯拐,多個字段也能使用逗號分隔的列表來指定霞篡。
GET /website/blog/123?_source=title,text
檢測文檔是否存在
如果只想檢查一個文檔是否存在 --根本不想關(guān)心內(nèi)容--那么用 HEAD 方法來代替 GET 方法世蔗。 HEAD 請求沒有返回體,只返回一個 HTTP 請求報頭:
curl -i -XHEAD http://localhost:9200/website/blog/123
如果文檔存在朗兵, Elasticsearch 將返回一個 200 ok 的狀態(tài)碼:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
若文檔不存在污淋, Elasticsearch 將返回一個 404 Not Found 的狀態(tài)碼:
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
更新文檔
在 Elasticsearch 中文檔是 不可改變 的,不能修改它們余掖。 相反寸爆,如果想要更新現(xiàn)有的文檔,需要 重建索引 或者進(jìn)行替換盐欺, 我們可以使用相同的 index API 進(jìn)行實(shí)現(xiàn)赁豆,在 索引文檔 中已經(jīng)進(jìn)行了討論。
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
在響應(yīng)體中找田,我們能看到 Elasticsearch 已經(jīng)增加了 _version 字段值:
如果返回體中created 標(biāo)志設(shè)置成 false 歌憨,是因?yàn)橄嗤乃饕㈩愋秃?ID 的文檔已經(jīng)存在墩衙。
在內(nèi)部,Elasticsearch 已將舊文檔標(biāo)記為已刪除甲抖,并增加一個全新的文檔漆改。 盡管你不能再對舊版本的文檔進(jìn)行訪問,但它并不會立即消失准谚。當(dāng)繼續(xù)索引更多的數(shù)據(jù)挫剑,Elasticsearch 會在后臺清理這些已刪除文檔。
在本章的后面部分柱衔,我們會介紹 update API, 這個 API 可以用于 partial updates to a document 樊破。 雖然它似乎對文檔直接進(jìn)行了修改,但實(shí)際上 Elasticsearch 按前述完全相同方式執(zhí)行以下過程:
- 從舊文檔中構(gòu)建json
- 更新該json
- 刪除舊文檔
- 索引一個新文檔
唯一的區(qū)別在于, update API 僅僅通過一個客戶端請求來實(shí)現(xiàn)這些步驟唆铐,而不需要單獨(dú)的 get 和 index 請求哲戚。
創(chuàng)建新文檔
當(dāng)我們索引一個文檔時 ,我們怎么確認(rèn)是在創(chuàng)建新的文檔艾岂,而不是覆蓋呢顺少?
index、type王浴、id可以標(biāo)識一個文檔脆炎,所以我們有兩種方式,這兩種實(shí)際上是做了一樣的事情氓辣。
PUT /website/blog/123/_create
PUT /website/blog/123?op_type=create
如果創(chuàng)建新文檔的請求成功執(zhí)行秒裕,Elasticsearch 會返回元數(shù)據(jù)和一個 201 Created 的 HTTP 響應(yīng)碼。
如果具有相同的 _index 钞啸、 _type 和 _id 的文檔已經(jīng)存在几蜻,Elasticsearch 將會返回 409 Conflict 響應(yīng)碼喇潘,以及如下的錯誤信息:
{
"error": {
"root_cause": [
{
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
}
],
"type": "document_already_exists_exception",
"reason": "[blog][123]: document already exists",
"shard": "0",
"index": "website"
},
"status": 409
}
刪除文檔
DELETE /website/blog/123
如果找到該文檔,Elasticsearch 將要返回一個 200 ok 的 HTTP 響應(yīng)碼入蛆,和一個類似以下結(jié)構(gòu)的響應(yīng)體响蓉。注意,字段 _version 值已經(jīng)增加:
{
"found" : true,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 3
}
如果文檔沒有 找到哨毁,我們將得到 404 Not Found 的響應(yīng)碼和類似這樣的響應(yīng)體:
{
"found" : false,
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 4
}
即使文檔不存在( Found 是 false )枫甲, _version 值仍然會增加。這是 Elasticsearch 內(nèi)部記錄本的一部分扼褪,用來確保這些改變在跨多節(jié)點(diǎn)時以正確的順序執(zhí)行想幻。
正如已經(jīng)在更新整個文檔中提到的,刪除文檔不會立即將文檔從磁盤中刪除话浇,只是將文檔標(biāo)記為已刪除狀態(tài)脏毯。隨著你不斷的索引更多的數(shù)據(jù),Elasticsearch 將會在后臺清理標(biāo)記為已刪除的文檔幔崖。
處理沖突
當(dāng)我們使用 index API 更新文檔 食店,可以一次性讀取原始文檔,做我們的修改赏寇,然后重新索引 整個文檔 吉嫩。 最近的索引請求將獲勝:無論最后哪一個文檔被索引,都將被唯一存儲在 Elasticsearch 中嗅定。如果其他人同時更改這個文檔自娩,他們的更改將丟失。
有的時候系統(tǒng)是不需要控制并發(fā)的
但是往往都是需要的
根據(jù)以往數(shù)據(jù)庫并發(fā)控制經(jīng)驗(yàn)渠退,通常有兩種方式控制:
- 悲觀并發(fā)控制
- 這種方式被數(shù)據(jù)庫廣泛的使用忙迁,比如innodb的行鎖排它鎖
- 樂觀并發(fā)控制
- 比如CAS,
ElasticSearch中使用的就是樂觀鎖碎乃,就是先假定沖突不會發(fā)生姊扔,不會阻塞的先操作,然而荠锭,如果源數(shù)據(jù)在讀寫當(dāng)中被修改旱眯,更新將會失敗。應(yīng)用程序接下來將決定該如何解決沖突证九。 例如删豺,可以重試更新、使用新的數(shù)據(jù)愧怜、或者將相關(guān)情況報告給用戶呀页。
樂觀并發(fā)控制
Elasticsearch 是分布式的。當(dāng)文檔創(chuàng)建拥坛、更新或刪除時蓬蝶, 新版本的文檔必須復(fù)制到集群中的其他節(jié)點(diǎn)尘分。Elasticsearch 也是異步和并發(fā)的,這意味著這些復(fù)制請求被并行發(fā)送丸氛,并且到達(dá)目的地時也許 順序是亂的 培愁。 Elasticsearch 需要一種方法確保文檔的舊版本不會覆蓋新的版本。
當(dāng)我們之前討論 index 缓窜, GET 和 delete 請求時定续,我們指出每個文檔都有一個 _version (版本)號,當(dāng)文檔被修改時版本號遞增禾锤。 Elasticsearch 使用這個 _version 號來確保變更以正確順序得到執(zhí)行私股。如果舊版本的文檔在新版本之后到達(dá),它可以被簡單的忽略恩掷。
我們可以利用 _version 號來確保 應(yīng)用中相互沖突的變更不會導(dǎo)致數(shù)據(jù)丟失倡鲸。我們通過指定想要修改文檔的 version 號來達(dá)到這個目的。 如果該版本不是當(dāng)前版本號黄娘,我們的請求將會失敗峭状。
// 先創(chuàng)建一個新的文檔
PUT /website/blog/1/_create
{
"title": "My first blog entry",
"text": "Just trying this out..."
}
//然后檢索看到version是1
GET /website/blog/1
{
"_index" : "website",
"_type" : "blog",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out..."
}
}
//現(xiàn)在,當(dāng)我們嘗試通過重建文檔的索引來保存修改逼争,我們指定 version 為我們的修改會被應(yīng)用的版本:
PUT /website/blog/1?version=1
{
"title": "My first blog entry",
"text": "Starting to get the hang of this..."
}
上述是內(nèi)部機(jī)制控制版本號
我們可以把版本號通過外部系統(tǒng)控制
外部版本號的處理方式和我們之前討論的內(nèi)部版本號的處理方式有些不同宁炫, Elasticsearch 不是檢查當(dāng)前 _version 和請求中指定的版本號是否相同, 而是檢查當(dāng)前 _version 是否 小于 指定的版本號氮凝。 如果請求成功,外部的版本號作為文檔的新 _version 進(jìn)行存儲望忆。
PUT /website/blog/2?version=5&version_type=external
{
"title": "My first external blog entry",
"text": "Starting to get the hang of this..."
}
注意罩阵,這里的version只能大,不能比ela中的小
文檔的部分更新
在 更新整個文檔 , 我們已經(jīng)介紹過 更新一個文檔的方法是檢索并修改它启摄,然后重新索引整個文檔稿壁,這的確如此。
然而歉备,使用 update API 我們還可以部分更新文檔傅是,例如在某個請求時對計數(shù)器進(jìn)行累加。
我們也介紹過文檔是不可變的:他們不能被修改蕾羊,只能被替換喧笔。
update API 必須遵循同樣的規(guī)則。 從外部來看龟再,我們在一個文檔的某個位置進(jìn)行部分更新书闸。
然而在內(nèi)部, update API 簡單使用與之前描述相同的 檢索-修改-重建索引 的處理過程利凑。
區(qū)別在于這個過程發(fā)生在分片內(nèi)部浆劲,這樣就避免了多次請求的網(wǎng)絡(luò)開銷嫌术。
通過減少檢索和重建索引步驟之間的時間,我們也減少了其他進(jìn)程的變更帶來沖突的可能性牌借。
update 請求最簡單的一種形式是接收文檔的一部分作為 doc 的參數(shù)度气, 它只是與現(xiàn)有的文檔進(jìn)行合并。
對象被合并到一起膨报,覆蓋現(xiàn)有的字段磷籍,增加新的字段。 例如丙躏,我們增加字段 tags 和 views 到我們的博客文章择示,如下所示:
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
使用腳本更新
這個暫不看了
更新的文檔可能不存在
假設(shè)我們需要 在 Elasticsearch 中存儲一個頁面訪問量計數(shù)器。 每當(dāng)有用戶瀏覽網(wǎng)頁晒旅,我們對該頁面的計數(shù)器進(jìn)行累加栅盲。但是,如果它是一個新網(wǎng)頁废恋,我們不能確定計數(shù)器已經(jīng)存在谈秫。 如果我們嘗試更新一個不存在的文檔,那么更新操作將會失敗鱼鼓。在這樣的情況下拟烫,我們可以使用 upsert 參數(shù),指定如果文檔不存在就應(yīng)該先創(chuàng)建它:
POST /website/pageviews/1/_update
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 1
}
}
//第一次運(yùn)行這個請求時迄本, upsert 值作為新文檔被索引硕淑,初始化 views 字段為 1 。 在后續(xù)的運(yùn)行中嘉赎,由于文檔已經(jīng)存在置媳, script 更新操作將替代 upsert 進(jìn)行應(yīng)用,對 views 計數(shù)器進(jìn)行累加公条。
沖突
如果沖突了拇囊,我們還想重試,比如計數(shù)器這個完全可以直接重試的操作
我們可以
POST /website/pageviews/1/_update?retry_on_conflict=5
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 0
}
}
//這里的5表示重試5次靶橱。
在增量操作無關(guān)順序的場景寥袭,例如遞增計數(shù)器等這個方法十分有效,但是在其他情況下變更的順序 是 非常重要的关霸。 類似 index API 传黄, update API 默認(rèn)采用 最終寫入生效 的方案,但它也接受一個 version 參數(shù)來允許你使用 optimistic concurrency control 指定想要更新文檔的版本谒拴。
取回多個文檔
Elasticsearch 的速度已經(jīng)很快了尝江,但甚至能更快。 將多個請求合并成一個英上,避免單獨(dú)處理每個請求花費(fèi)的網(wǎng)絡(luò)延時和開銷炭序。
如果你需要從 Elasticsearch 檢索很多文檔啤覆,那么使用 multi-get 或者 mget API 來將這些檢索請求放在一個請求中,將比逐個文檔請求更快地檢索到全部文檔惭聂。
mget API 要求有一個 docs 數(shù)組作為參數(shù)窗声,每個 元素包含需要檢索文檔的元數(shù)據(jù), 包括 _index 辜纲、 _type 和 _id 笨觅。
如果你想檢索一個或者多個特定的字段,那么你可以通過 _source 參數(shù)來指定這些字段的名字:
示例:
GET /_mget
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : 2
},
{
"_index" : "website",
"_type" : "pageviews",
"_id" : 1,
"_source": "views"
}
]
}
該響應(yīng)體也包含一個 docs 數(shù)組 耕腾, 對于每一個在請求中指定的文檔见剩,這個數(shù)組中都包含有一個對應(yīng)的響應(yīng),且順序與請求中的順序相同扫俺。 其中的每一個響應(yīng)都和使用單個 get request 請求所得到的響應(yīng)體相同:
{
"docs" : [
{
"_index" : "website",
"_id" : "2",
"_type" : "blog",
"found" : true,
"_source" : {
"text" : "This is a piece of cake...",
"title" : "My first external blog entry"
},
"_version" : 10
},
{
"_index" : "website",
"_id" : "1",
"_type" : "pageviews",
"found" : true,
"_version" : 2,
"_source" : {
"views" : 2
}
}
]
}
如果想檢索的數(shù)據(jù)都在相同的 _index 中(甚至相同的 _type 中)苍苞,則可以在 URL 中指定默認(rèn)的 /_index 或者默認(rèn)的 /_index/_type 。
你仍然可以通過單獨(dú)請求覆蓋這些值:
GET /website/blog/_mget
{
"docs" : [
{ "_id" : 2 },
{ "_type" : "pageviews", "_id" : 1 }
]
}
事實(shí)上狼纬,如果所有文檔的 _index 和 _type 都是相同的羹呵,你可以只傳一個 ids 數(shù)組,而不是整個 docs 數(shù)組:
GET /website/blog/_mget
{
"ids" : [ "2", "1" ]
}
注意疗琉,我們請求的第二個文檔是不存在的冈欢。我們指定類型為 blog ,但是文檔 ID 1 的類型是 pageviews 盈简,這個不存在的情況將在響應(yīng)體中被報告:
{
"docs" : [
{
"_index" : "website",
"_type" : "blog",
"_id" : "2",
"......
},
{
"_index" : "website",
"_type" : "blog",
"_id" : "1",
"found": false
}
]
}
事實(shí)上第二個文檔未能找到并不妨礙第一個文檔被檢索到凑耻。每個文檔都是單獨(dú)檢索和報告的。
實(shí)際上就算都沒有找到柠贤,請求Http碼依舊是200拳话,因?yàn)檫@個主體是megt請求。
代價較小的批量操作
與 mget 可以使我們一次取回多個文檔同樣的方式种吸, bulk API 允許在單個步驟中進(jìn)行多次 create 、 index 呀非、 update 或 delete 請求坚俗。
如果你需要索引一個數(shù)據(jù)流比如日志事件,它可以排隊和索引數(shù)百或數(shù)千批次岸裙。bulk 與其他的請求體格式稍有不同猖败,如下所示:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...
這種格式類似一個有效的單行 JSON 文檔 流 ,它通過換行符(\n)連接到一起降允。注意兩個要點(diǎn):
- 每行一定以換行符結(jié)束恩闻,包括最后一行,這就是一行結(jié)束的標(biāo)記
- 這些行不能包含未轉(zhuǎn)義的換行符剧董,因?yàn)樗麄儗馕鲈斐筛蓴_幢尚。這意味著這個 JSON 不 能使用 pretty 參數(shù)打印破停。
action/metadata 行指定 哪一個文檔 做 什么操作 。
action 必須是以下選項(xiàng)之一:
- create
- 如果文檔不存在尉剩,那么就創(chuàng)建它真慢。詳情請見 創(chuàng)建新文檔。
- index
- 創(chuàng)建一個新文檔或者替換一個現(xiàn)有的文檔理茎。詳情請見 索引文檔 和 更新整個文檔黑界。
- update
- 部分更新一個文檔。詳情請見 文檔的部分更新皂林。
- delete
- 刪除一個文檔朗鸠。詳情請見 刪除文檔。
metadata 應(yīng)該 指定被索引础倍、創(chuàng)建烛占、更新或者刪除的文檔的 _index 、 _type 和 _id 著隆。
例如扰楼,一個 delete 請求看起來是這樣的:
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
- request body 行由文檔的 _source 本身組成--文檔包含的字段和值。
- 它是 index 和 create 操作所必需的美浦,這是有道理的:你必須提供文檔以索引弦赖。
- 它也是 update 操作所必需的,并且應(yīng)該包含你傳遞給 update API 的相同請求體: doc 浦辨、 upsert 蹬竖、 script 等等。
- 刪除操作不需要 request body 行流酬。
示例:
POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
{ "doc" : {"title" : "My updated blog post"} }
- 注意delete動作下沒有請求體币厕,他后面跟著另一個操作
- 最后一個換行符不要忘了。
這個 Elasticsearch 響應(yīng)包含 items 數(shù)組芽腾, 這個數(shù)組的內(nèi)容是以請求的順序列出來的每個請求的結(jié)果旦装。
{
"took": 4,
"errors": flase,
"items": [
{ "delete": {
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 2,
"status": 200,
"found": true
}},
.....
]
}
每個子請求都是獨(dú)立執(zhí)行,因此某個子請求的失敗不會對其他子請求的成功與否造成影響摊滔。 如果其中任何子請求失敗阴绢,最頂層的 error 標(biāo)志被設(shè)置為 true ,并且在相應(yīng)的請求報告出錯誤明細(xì):
- bulk 請求不是原子的: 不能用它來實(shí)現(xiàn)事務(wù)控制艰躺。
- 每個請求是單獨(dú)處理的呻袭,因此一個請求的成功或失敗不會影響其他的請求。
不要重復(fù)制定INdex和Type
也許你正在批量索引日志數(shù)據(jù)到相同的 index 和 type 中腺兴。
但為每一個文檔指定相同的元數(shù)據(jù)是一種浪費(fèi)左电。
相反,可以像 mget API 一樣,在 bulk 請求的 URL 中接收默認(rèn)的 /_index 或者 /_index/_type :
POST /website/_bulk
{ "index": { "_type": "log" }}
{ "event": "User logged in" }
你仍然可以覆蓋元數(shù)據(jù)行中的 _index 和 _type , 但是它將使用 URL 中的這些元數(shù)據(jù)值作為默認(rèn)值:
POST /website/log/_bulk
{ "index": {}}
{ "event": "User logged in" }
{ "index": { "_type": "blog" }}
{ "title": "Overriding the default type" }
大小控制
整個批量請求都需要由接收到請求的節(jié)點(diǎn)加載到內(nèi)存中篓足,因此該請求越大段誊,其他請求所能獲得的內(nèi)存就越少。 批量請求的大小有一個最佳值纷纫,大于這個值枕扫,性能將不再提升,甚至?xí)陆怠?br>
但是最佳值不是一個固定的值辱魁。
它完全取決于硬件烟瞧、文檔的大小和復(fù)雜度、索引和搜索的負(fù)載的整體情況染簇。
幸運(yùn)的是参滴,很容易找到這個 最佳點(diǎn) :
通過批量索引典型文檔,并不斷增加批量大小進(jìn)行嘗試锻弓。
當(dāng)性能開始下降砾赔,那么你的批量大小就太大了。
一個好的辦法是開始時將 1,000 到 5,000 個文檔作為一個批次, 如果你的文檔非常大青灼,那么就減少批量的文檔個數(shù)暴心。
一個好的批量大小在開始處理后所占用的物理大小約為 5-15 MB。