LoginSignup
19
9

More than 3 years have passed since last update.

Elasticsearchで不要なフィールドの削除

Last updated at Posted at 2019-10-01

使用されなくなった古いフィールドを削除したい。
フィールドを消すにはidを指定して次の_updateクエリを実行するか、

kibana/DevTools
POST test/1/_update
{
  "script": "ctx._source.remove('field_to_delete')",
}

フィールドをもつドキュメントすべてに対して削除したい場合はexitsクエリで絞って_update_by_queryを実行する。

kibana/DevTools
POST test/_update_by_query
{
  "script": "ctx._source.remove('field_to_delete')",
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "field_to_delete"
          }
        }
      ]
    }
  }
}

しかし、exitsクエリはフィールドがnullかつnull_valueの設定をしていない場合、フィールドを持っていないと判断してしまう。つまり、不要なフィールドがnullの場合は検索結果に入ってこない。

existsクエリ
null_valueの設定をすればnullは検索できる

厄介なこととして、例えば、上の更新コマンドを実行中に処理を誤って中断してしまった場合や、全て削除したにも関わらず、そのあと追加されたドキュメントが不要なフィールドを持っていた場合、同じインデックス内に不要フィールドを持っているやつと持っていないやつが混在することになる。

その場合、例えば厳密にentityの型を定義しているデータマイニングツールなどでは、処理の途中でカラム数が合わず処理が失敗する可能性がある。

そうでなくても、同じインデックス内にフィールドのあるなしのドキュメントが混在するのはよくない。

しかし、データ量が多く、全データに対してなにかやるのは嫌だけど、不要なフィールドを持っているドキュメントだけを検索してやっつけるということができないので割と困った。

対応方法①:全データに対して_update_by_query

やはり、全件検索をするのは免れなそう。
ただし、消したいフィールドを含むドキュメントだけ削除するようにすることができるので処理速度をある程度削減できた。
(全ドキュメントに不要なフィールドがある場合は効果なしだと思われる)

POST test/_update_by_query
{
  "script": {
    "source": """
        if (ctx._source.containsKey('field_to_delete')) {
            ctx._source.remove('field_to_delete');
        } else {
          ctx.op='noop';
        }
"""
  }
}

ステータスの確認は以下を実行する。

GET _tasks?detailed=true&actions=*update*

次のような結果がかえってくる

{
  "nodes" : {
    "qsJdt39QT0uDGRMhIb468w" : {
      ...
      "tasks" : {
        "qsJdt39QT0uDGRMhIb468w:59320333" : {
          ...
          "status" : {
            "total" : 10000
            "updated" : 10,
            ...
            "noops" : 174885,
            ...
          },
          ...
        }
      }
    }
  }
}

total10000件に対して、updatedが10件、noopsが174885件とどれくらい不要なフィールドがあったのか確認することができる。

対応方法②:reindex

不要なフィールドが全てnullの場合(existsを使った検索が0件ならば、逆に全てがnullであるといえる)新しいマッピング定義を行ったインデックスに対してreindexをすることで不要なフィールドを取り除くことができる。

ただし、大量のデータの場合、一時的でもデータ量が2倍になるので、ディスク容量などに余裕が必要となるので注意が必要。

参考

https://stackoverflow.com/questions/29002215/remove-a-field-from-a-elasticsearch-document
https://stackoverflow.com/questions/56649273/elasticsearch-delete-field-from-all-documents-where-it-exists-with-painless

19
9
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
19
9