ドキュメントを読みましょう、というだけなんですが…。
noop update
elasticsearchのupdateにはnoop update
という仕組みがあり、同じ内容のドキュメントでアップデートしようとしてもキャンセルされてアップデートは実施されず、インデクシングは生じない。これは、各ドキュメントの"_version"が上がらないことで確認できる。
PUT /test_noop_update/
POST /test_noop_update/_doc/1
{
"foo":"baa"
}
GET /test_noop_update/_doc/1
POST /test_noop_update/_update/1
{
"doc":{
"foo":"baa"
}
}
{
"_index" : "test_noop_update",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "noop", //<--updateが実施されなかったことが分かる。
"_shards" : {
"total" : 0,
"successful" : 0,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
GET /test_noop_update/_doc/1
{
"_index" : "test_noop_update",
"_type" : "_doc",
"_id" : "1",
"_version" : 1, //<-- 1のまま
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"foo" : "baa"
}
}
ingest_pipelineとdoc_as_upsertを併用すると、noop updateにならないことがある
Logstashを利用してupdateする際に文書の重複への対処としてIDをfingerprintで採番してdoc_idを付与していたのだが、同じ内容の文書であってもアップデートされてしまい、"_version"が変わってしまっていた。
elasticsearch単体で実験してみると、
PUT /test_noop_update/
{
"settings": {
"index":{
"default_pipeline": "last_updated_timestamp_pipeline"
}
}
}
POST /test_noop_update/_doc/1
{
"foo":"baa"
}
POST /test_noop_update/_bulk
{"update":{"_id":1}}
{"doc": {"foo":"baa"}}
{"update":{"_id":1}}
{"doc": {"foo":"baa"}, "doc_as_upsert":true}
{"update":{"_id":1}}
{"doc": {"foo":"baa"}, "upsert":{}}
{
"took" : 19,
"ingest_took" : 0,
"errors" : false,
"items" : [
{
"update" : {
"_index" : "test_noop_update",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "noop", //<--ok
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1,
"status" : 200
}
},
{
"update" : {
"_index" : "test_noop_update",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated", //<-- doc_as_upsert使用時のみ"updated"に。
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1,
"status" : 200
}
},
{
"update" : {
"_index" : "test_noop_update",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "noop", //<--ok
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1,
"status" : 200
}
}
]
}
doc_as_upsert使用時のみ"updated"になっている。まとめると、
ingest_pipelineなし
action | parameter | _version |
---|---|---|
index | +1 | |
update | - | |
update | upsert:{} | - |
update | doc_as_upsert | - |
ingest_pipelineあり
action | parameter | _version |
---|---|---|
index | +1 | |
update | - | |
update | upsert:{} | - |
update | doc_as_upsert | +1 |
と、ingest_piplineを併用している場合、doc_as_upsert
のみnoop update
が生じずに、同じdocumentにも関わらず通常のupdateが発生してしまっていた(なおこの挙動は毎回生じるものなのか、ingest pipelineの内容といった状況次第なのかは分からない)。
ここで初めてelasticsearch側のドキュメントを確認すると、
NOTE: Using ingest pipelines with doc_as_upsert is not supported.
とあり、どうやらingest_pipeline
とdoc_as_upsert
を同時に使用することは非推奨で、upsert
を使いましょう、ということでした。upsert
でドキュメントと同じ内容のjsonを指定すると同じ効果が得られます。
教訓
ドキュメントをきちんと読みましょう。