ひげぶろぐ

開発とか組織とかの話

Amazon Elasticsearch Service でインデクシングされなくなった時の調査・解決ログ

AWS Amplify の @searchable を使って Elasticsearch による検索を実現していたのですが、ある時から突然、新しくDynamoDBに登録したデータが検索に引っかからなくなりました。
そんな時のメモ。

状況

  • 検索機能を作って最初のうちは普通に検索が出来ていた
  • スキーマ変更、データの形式変更(日付データのフォーマット変更等)を行なってからうまくいかなくなった
  • スキーマ変更の直後にスクリプトで大量にデータを投入していたが、スキーマ変更したテーブルだけうまくいっていなかった

引っかからない理由の調査

検索に引っかからない理由はいくつか考えられた。
まずいくつかあたりをつけてみる。
今回なら以下のような感じ。

  • 1 : 検索のコードが良くない
  • 2 : インフラの構成がおかしい
  • 3 : cliからのデータ登録だとインデクシングされない
  • 4 : スキーマ変更が影響した
  • 5 : データのフォーマット変更が影響した

今回は amplify env add で同じ構成の別環境を作って色々と試し、結果として 1,2,3,4 は原因でないことが分かった。

調査の中で Elastic Search の index 状況を見る場面があったが、その際、検索がうまくいかないテーブルのインデックスが明らかにデータ数に対して少ないことが分かった。
検索に引っかからないのはそもそもインデクシングされていないからだと判明した。

インデクシングされない原因の調査

インデクシングの処理の流れとしては、DynamoDBにデータが登録された時にLambdaが走り、Elasticsearch Serviceに届く形である。
したがってLambdaが怪しい。

AWS ConsoleでLambdaを見ると、DdbToEsFn-hogehoge-env というFunctionが出来ている。
これが DynamoDBからElasticsearchServiceへデータを送る関数。

サービスにアクセスして(或いはcli等で)DynamoDBにデータを流し込み、モニタリング > CloudWatch Logs Insights でログを監視してみる。
すると見事にエラーが出ていた。

{
  "took":9,
  "errors":true,
  "items":
  [
    {"index":
      {"_index":"user",
        "_type":"doc",
        "_id":"XXX",
        "status":400,
        "error":{
          "type":"mapper_parsing_exception",
          "reason":"failed to parse [birthday]",
          "caused_by":{
            "type":"illegal_argument_exception",
            "reason":"Invalid format: \\"01/01\\" is too short"
          }
        }
      }
    }
  ]
}

調べてみると、Elasticsearch のスキーマ自動マッピング機能が問題だった。
yyyy/mm/dd形式の日付のデータを数件入れた後で、それをmm/ddに変更した為、自動生成されたフォーマットに合わずに弾かれていたようだ。
これで原因が分かった。

インデクシングしない問題の解決

既存のマッピングが悪いので、これを書き換えるか削除して作り直すかすれば良い。
今回はデータ量も少なかったので作り直す方針をとる。(というかAWSマッピング更新している事例が見つからなかった)

作り直しといっても、既存のindexを削除してデータを再度流し込むだけ。
だが、indexの削除をconsoleやcliから実行する手段は見当たらなかった。
面倒だったがLambdaからCuratorを使って削除した。

▼ 参考

inside.dmm.com

そんなわけで調査と解決にやたら時間がかかったけど解決。
Dynamoスキーマ変更に強いと言っても、Elasticsearchを使うなら出来る限りスキーマは変えたくないなあと思った次第。