LoginSignup
1
0

More than 1 year has passed since last update.

ingest pipelineはdoc_as_upsertではなくupsertと使う

Last updated at Posted at 2022-01-26

ドキュメントを読みましょう、というだけなんですが…。

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_pipelinedoc_as_upsertを同時に使用することは非推奨で、upsertを使いましょう、ということでした。upsertでドキュメントと同じ内容のjsonを指定すると同じ効果が得られます。

教訓

ドキュメントをきちんと読みましょう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0