目次
全文検索のメリットは?
ECサイトに限りませんが、パフォーマンスはユーザービリティに直結するため、「サクサク動く」サイトを担保するのは重要です。
パフォーマンス低下はいろいろな要因がありますが、ECサイトにおいてよく見られるパフォーマンス低下の一つが、商品検索にかかる処理です。
商品の増加に従い、検索対象データが増えることで、検索処理が重くなっている状況です。
当社で日頃から扱っているEC-CUBEにおいても、商品が多くなると、検索パフォーマンスは低下します。
こうした商品検索処理のパフォーマンス改善を行う時に、まず最初にオススメするのが「全文検索」です。
全文検索は外部ツールを利用しないため、実質無料で導入できるほか、導入も比較的容易だというメリットがあります。
導入の際にいくつか注意点はありますが、全文検索は数十万点のサイトでも高速な検索が可能であり、最初に試して損はない方法です!
※ちなみにパフォーマンス改善に関しては、いろいろな方法があるので、以下ページも参考にしてください。
https://regolith.diezon.co.jp/acceleration
全文検索とは?
まずは全文検索の仕組みをご説明します。
全文検索は大きく分けgrep型と索引(インデックス)型の2つに大別することができます。
① grep型とは?
grep型は、テキストデータを一つ一つ順番に読み込み、キーワードと一致するかどうかを確認していく方法になります。
非常にシンプルな手法で、一つずつチェックをしていくので検索精度は非常に高いのですが、その分検索に時間がかかってしまうというデメリットも存在します。
ECサイトの商品数が増えれば増えるほど、検索速度が低下してしまうので検索の高速化という点では向いていません。
② 索引(インデックス)型
索引(インデックス)型は、あらかじめ索引情報(インデックス)を作っておくことで、素早く検索できるようにする方法です。
例えば辞書で「日本」という単語を最初のページから探していくのは大変ですが、索引を見ればより簡単に調べることができますね。
これと同じような原理であらかじめ索引情報(インデックス)を用意しておくことでgrep型に比べて検索の高速化を実現することができます。
一方でgrep型に比べると、索引(インデックス)を利用する特性上、検索精度が低くなってしまうため、意図しない検索結果を得られない場合があります。
N-gramを使った全文検索の仕組みについて
今回の記事で紹介する「全文検索」は、索引(インデックス)型のN-gramという手法を使った方法になります。
この後記載する注意点にも関係してくるため、少しN-gramの特徴を記載しておきます。
① 索引(インデックス)型のN-gram方式とは
索引(インデックス)型のN-gram方式は、指定した文字数で検索対象のテキストデータを分解してインデックスを生成する方法になります。
例えば、N-gramの値を2に設定し、「全文検索処理」というワードで検索したケースを想定してみます。
この場合には次のように2文字区切りのインデックスが生成されます。
全文
文検
検索
索処
処理
このように事前に指定した値の数値で区切ったインデックスを生成することで検索処理を高速化することができます。
ちなみに、MySQLのN-gramの設定値はデフォルトで2になります。
N-gramを使った全文検索をECCUBEで導入する時に注意すべき3つのポイント
この仕組みを比較的容易に導入できることは、既に記載の通りではありますが、導入時に注意が必要な点もあります。それが主に次の3点です。
- 検索単語が1文字の場合を考慮する
- 検索単語が記号の場合に注意する
- Proxy再生成の際に、Entityからindexが外れないように対応する
それぞれ解説していきます。
① 検索単語が1文字の場合を考慮する
N-gramの設定値を2に設定していた場合には、1文字の検索キーワードがヒットしなくなってしまいます。
そのため検索キーワードが1文字の場合にはEC-CUBE既存の検索処理を実行し、2文字以上の場合には全部検索の処理を実行するように条件分岐をする必要があります。
具体的には以下のようなコードになります。
if (mb_strlen($keyword) === $this->eccubeConfig['not_full_text_search_keyword_length']) { $condition .= $this->productRepository->getProductSearchCondition($key); $builder->setParameter($key, '%' . $keyword . '%'); } else { $condition .= sprintf('( MATCH(p.name, p.item_code) AGAINST(:%s IN BOOLEAN MODE) > 0 OR MATCH(p.search_word) AGAINST(:%s IN BOOLEAN MODE) > 0)', $key, $key); $builder->setParameter($key, $keyword); }
② 検索単語が記号の場合に注意する
N-gramを使った全文検索では、「検索ワードに記号使えない」という特性があります。
例えば、「◎」・「&」・「〇」・「※」などのように記号を含むキーワードで検索した場合、エラーが生じます。
そのため当社ではあらかじめ使用想定のある記号を洗い出し、対象の記号が検索フォームで使用された場合にはスペースとして変換して検索処理を実行するように対応しています。
③ Proxy再生成の際に、Entityからindexが外れないように対応する
DBに変更を加える際には、Proxyの再生成コマンドを実施する場面が多いです。
コマンド:bin/console eccube:generate:proxies
その際にEntityファイルにindexが外れないためのコードを追加しておかないと、上記コマンド実行時にindexが外れてしまい検索処理実行時にシステムエラーが発生してしまいます。
具体的には以下のようなコードを対象のEntityに記載する必要があります。
* @ORMTable(name="dtb_product", indexes={ * @ORMIndex(columns={"name"}), * @ORMIndex(columns={"item_code"}), * @ORMIndex(name="ft_idx_search_word", columns={"search_word"}, flags={"fulltext"}), * @ORMIndex(name="ft_idx_name_item_code", columns={"name","item_code"}, flags={"fulltext"}), * })
おわりに
今回は検索高速化における「全文検索」の概要や導入時に気を付けるポイントなどについて解説してきました。
EC-CUBEにおいて検索処理を高速化する方法はいくつかありますが、その中でも比較的容易に導入できるのが今回紹介した「全文検索」になります。
全体的なトレンドとしては、外部の検索ツールを連携させることが多いですが、外部ツールは利用料と開発工数がかかるので、まずは全文検索で検索パフォーマンスがどのくらい改善されるのかを検証してみて、さらに速度を改善したいという場合には外部の検索ツールの導入を検討してみても良いかもしれませんね。
以下記事にて、全文検索以外の高速化に関するご紹介もしておりますので、併せてご覧くださいませ。
https://regolith.diezon.co.jp/column/ec28_speeding
最後までお読みいただきましてありがとうございました。