はじめに
こんにちは、デリッシュキッチン開発部でソフトウェアエンジニアをしている新谷です。
エブリーの開発部では「挑戦week」という1週間の期間限定チャレンジを定期的に開催しています。これは日常業務から離れて、新しい技術やアイデアに挑戦する取り組みです。 今回は、この挑戦week期間中にデリッシュキッチンの検索基盤をElasticsearchからOpenSearchへ移行する挑戦を行いましたので、その内容を紹介します。
※ 挑戦weekの詳細については過去の記事で紹介していますので、興味のある方は以下をご覧ください。
背景:なぜElasticsearchの移行が必要なのか
デリッシュキッチンでは、レシピ検索とサジェスト機能のために長らくElasticsearch 5.5をECS上で運用してきましたが、以下のような課題がありました。
- バージョンの古さ:Elasticsearch 5.5は既に数年前のバージョンであり、セキュリティ面や機能面で最新版に劣っています
- 検索周りの施策展開の困難さ:古いバージョンであるため、新しい検索機能の実装が難しくなっていました
- 運用負荷:ECS上での自前運用による保守管理コストがかかっていました
これらの課題を解決するために、ElasticsearchからAWSが主導開発しているOpenSearchへの移行を検討することになりました。
ElasticsearchとOpenSearchとは
OpenSearchはElasticsearchからフォークする形で誕生したオープンソースの検索エンジンです。元々Elasticsearchは完全なオープンソースでしたが、Elastic社はバージョン7.11以降からライセンスをElastic License 2.0に変更しました。これに対しAWSは「完全にオープンソース」の状態を維持するためにOpenSearchというフォークプロジェクトを立ち上げました。
現在、それぞれの開発は並行して進められていますが、AWS上のマネージドサービスとしてはOpenSearchが優先的にサポートされています。
項目 | Elasticsearch 7.11以降 | OpenSearch |
---|---|---|
ライセンス | Elastic License 2.0 / SSPL | Apache License 2.0 |
商用利用 | 制限あり(SaaS提供には制限) | 完全に自由 |
ソースコードの変更と再配布 | 許可されるが制限あり | 完全に自由 |
SaaS提供 | 制限あり | 制限なし |
開発主体 | Elastic社 | AWS主導のコミュニティ開発 |
挑戦weekでの取り組み
「挑戦week」というわずか1週間のプロジェクト期間と3人という少人数チームでの取り組みだったため、移行にあたっては現実的な範囲で以下のようなステップを設定しました。
- ローカル環境でのOpenSearchの導入
- ローカル環境での動作検証
- (将来的に実施)AWS インフラ構築
- (将来的に実施)CI 整備
当初は4つのステップすべてに挑戦する予定でしたが、実際に取り組んでみると想定以上に複雑な課題が見つかり、一週間では最初の2ステップである検証部分しか実施できませんでした。それでも、この限られた期間で多くの貴重な知見を得ることができました。
実施内容:ローカル環境での検証
ローカル環境でElasticsearchからOpenSearchへ切り替えるために、以下の作業を行いました。
Docker環境の整備
OpenSearchのDockerコンテナを使用するように設定を変更するため、Dockerfileの修正を行いました。具体的には、elasticsearch/elasticsearch
から opensearchproject/opensearch
へDockerイメージを変更しています。また、docker-compose.ymlも対応する形で修正し、ローカルでOpenSearchを立ち上げられるようにしました。
クライアントライブラリの検証
デリッシュキッチンではGoのクライアントライブラリとしてgopkg.in/olivere/elastic.v5
を使用していましたが、OpenSearchへの移行に伴い、opensearch-project/opensearch-go/v4
への切り替えが必要になりました。
検証の結果、以下のような課題が見つかりました。
- 数十メソッドの書き換えが必要
- 新しいライブラリは比較的薄いため、リクエストボディを自前で組み立てる必要がある
当初の想定を大きく上回る作業量が必要であることが判明しました。一週間の限られた時間では全容を把握するだけでも大変でした。
データ投入スクリプトの整備
OpenSearchにテストデータを投入するために、スクリプト化してmakeコマンドから実行できるように改善しました。これにより、繰り返しテストを行いやすくなりました。
主な技術的課題
検証過程で明らかになった主な変更点と課題について解説します。
1. _typeパラメーターの廃止
Elasticsearch 5.5では_type
パラメータを使用して、1つのインデックス内で異なる種類のドキュメントを区別していました。しかし、OpenSearch 2.19では_type
は完全に廃止され、1インデックス1種類のドキュメントという設計に変更されています。
当初のマッピング定義では、ingredients、recipes、tagsの3つのドキュメントが1つのインデックスで定義されており、投入時に_type=recipes
を指定することで対応していました。移行するには、「recipes」だけの定義に変更し、_type
指定なしでも動作するように修正する必要があります。
これはデータ構造の見直しを意味し、単純な置き換えでは解決できない課題です。
2. インデックスマッピングの厳格化
OpenSearch 2.19ではマッピングの制約が強化されています。特にシノニム(同義語)の設定ファイルに関して、Elasticsearch 5.5では許容されていた一部不適切な定義がOpenSearchではエラーとなりました。
具体的には、以下のようなシノニム定義ファイルの問題が見つかりました。
- 形式が不正な同義語の定義
- 重複する定義
- 解析できない文字が含まれる定義
一週間で全て修正するには時間が足りないため、一時的な対応としてシノニム部分に"lenient": true
定義を追加し、問題のある行があっても無視するよう対応しました。本来は、シノニム定義を見直し、問題のある行を修正する必要があります。
3. クエリ仕様の変更
OpenSearch 2.19ではboolクエリのパフォーマンスが向上しているというメリットがありますが、以下のような変更点がありました。
_all
フィールドの削除(元々falseで使用していなかったため、定義自体を削除)allow_leading_wildcard
のデフォルト無効化default_field
の明示的指定必須化- その他、細かな仕様変更
これらの変更により、既存の検索クエリの多くを見直す必要があり、検索結果への影響を一つひとつ検証する必要があります。
4. xpackプラグイン
xpackプラグインについては、OpenSearchではサポートされていないため、代替機能の検討が必要です。一週間という限られた時間内では、詳細な検討までは至りませんでした。
検索品質の検証結果
ローカル環境での検証後、実際の検索品質を評価するために比較テストを行いました。直近のアクセスログから1,000件の検索ワードをサンプリングし、ElasticsearchとOpenSearchの両方で検索して結果を比較しました。以下が比較した結果の一部です。
結果としては、どちらも一定の妥当性のある検索結果が得られましたが、複数の問題点が発覚しました。
1. 検索結果の品質低下
特定の検索ワードでOpenSearchのほうが劣っているケースが見つかりました。例えば、「麻薬たまご」という検索ワードでは、以下のような違いがありました。
- Elasticsearch: 「麻薬たまご」が一つの検索語として扱われ、「麻薬卵」レシピがヒット
- OpenSearch: 「麻」「薬」「た」「ま」「ご」のように分かれてしまい、「麻薬卵」レシピがヒットしない
このような違いは、トークナイザーやアナライザーの設定の違いによるものと考えられます。
2. その他の課題
検証結果から、ElasticsearchとOpenSearchにおいて明確に差異はありますが、なぜ差異がありどのようなパターンで差異が出るのかは明確になっていません。 「麻薬卵」は一例であり、その他の差異については検討が必要です。
今後の検討事項
挑戦weekの取り組みで明らかになった課題を踏まえ、今後取り組むべき検討事項は以下の通りです。
1. シノニム・辞書整備
- 現状の問題のある定義を洗い出して、Elasticsearchのシノニム定義をOpenSearchのシノニム定義に変更
- 日本語形態素解析の設定見直し、Elasticsearchと同等の設定にする
2. 段階的移行計画
- ユーザー体験の急激な変化を避けるため、段階的な移行を立てる
- 一度にOpenSearchに移行するのではなく、ElasticsearchとOpenSearchを共存させ、カナリアリリースを行う等の方法を検討
3. 検索品質の評価方法の検討
- 実践投入に向け、0件ヒット率等の検索品質の評価方法を検討する
まとめ
挑戦week前は、ElasticsearchとOpenSearchの知識がほぼない状態でスタートしましたが、シノニムの設定方法からそれぞれの仕様差分まで一週間で学び、良い経験になりました。 実際に取り組んでみて、単なるバージョンアップではなく、アーキテクチャの見直しを含む大規模なプロジェクトになることが分かりました。
短期間の検証ではありましたが、今後も機会を見つけてさらなる検証と課題解決を進め、最終的には検索機能の品質を向上させる形での移行を目指したいと思います。