楽観的同時実行制御
Elasticsearchは分散型です。ドキュメントが作成、更新、または削除されると、新しいバージョンのドキュメントはクラスター内の他のノードに複製される必要があります。Elasticsearchは非同期かつ同時実行であり、これらの複製リクエストは並行して送信され、宛先に到着する順序が異なる場合があります。Elasticsearchは、古いバージョンのドキュメントが新しいバージョンを上書きしないようにする方法が必要です。
古いバージョンのドキュメントが新しいバージョンを上書きしないようにするために、ドキュメントに対して実行されるすべての操作には、その変更を調整するプライマリシャードによってシーケンス番号が割り当てられます。シーケンス番号は各操作ごとに増加し、そのため新しい操作は古い操作よりも高いシーケンス番号を持つことが保証されます。Elasticsearchは、操作のシーケンス番号を使用して、新しいドキュメントバージョンが小さいシーケンス番号が割り当てられた変更によって上書きされないようにします。
たとえば、次のインデックス作成コマンドはドキュメントを作成し、初期シーケンス番号とプライマリタームを割り当てます:
Python
resp = client.index(
index="products",
id="1567",
document={
"product": "r2d2",
"details": "A resourceful astromech droid"
},
)
print(resp)
Ruby
response = client.index(
index: 'products',
id: 1567,
body: {
product: 'r2d2',
details: 'A resourceful astromech droid'
}
)
puts response
Js
const response = await client.index({
index: "products",
id: 1567,
document: {
product: "r2d2",
details: "A resourceful astromech droid",
},
});
console.log(response);
コンソール
PUT products/_doc/1567
{
"product" : "r2d2",
"details" : "A resourceful astromech droid"
}
割り当てられたシーケンス番号とプライマリタームは、応答の_seq_no
および_primary_term
フィールドに表示されます:
コンソール-結果
{
"_shards": {
"total": 2,
"failed": 0,
"successful": 1
},
"_index": "products",
"_id": "1567",
"_version": 1,
"_seq_no": 362,
"_primary_term": 2,
"result": "created"
}
Elasticsearchは、保存している各ドキュメントの最後の操作のシーケンス番号とプライマリタームを追跡します。シーケンス番号とプライマリタームは、GET APIの応答の_seq_no
および_primary_term
フィールドに返されます:
Python
resp = client.get(
index="products",
id="1567",
)
print(resp)
Ruby
response = client.get(
index: 'products',
id: 1567
)
puts response
Js
const response = await client.get({
index: "products",
id: 1567,
});
console.log(response);
コンソール
GET products/_doc/1567
コンソール-結果
{
"_index": "products",
"_id": "1567",
"_version": 1,
"_seq_no": 362,
"_primary_term": 2,
"found": true,
"_source": {
"product": "r2d2",
"details": "A resourceful astromech droid"
}
}
注: Search APIは、seq_no_primary_term
パラメータを設定することで、各検索ヒットの_seq_no
および_primary_term
を返すことができます。
シーケンス番号とプライマリタームは、変更を一意に識別します。返されたシーケンス番号とプライマリタームを記録することで、取得した後に他の変更が行われていない場合にのみドキュメントを変更することができます。これは、index API、update API、またはdelete APIのif_seq_no
およびif_primary_term
パラメータを設定することで行われます。
たとえば、次のインデックス作成呼び出しは、他のAPIによる説明の変更や別のタグの追加を失うことなく、ドキュメントにタグを追加することを保証します:
Python
resp = client.index(
index="products",
id="1567",
if_seq_no="362",
if_primary_term="2",
document={
"product": "r2d2",
"details": "A resourceful astromech droid",
"tags": [
"droid"
]
},
)
print(resp)
Js
const response = await client.index({
index: "products",
id: 1567,
if_seq_no: 362,
if_primary_term: 2,
document: {
product: "r2d2",
details: "A resourceful astromech droid",
tags: ["droid"],
},
});
console.log(response);
コンソール
PUT products/_doc/1567?if_seq_no=362&if_primary_term=2
{
"product": "r2d2",
"details": "A resourceful astromech droid",
"tags": [ "droid" ]
}