mt-ftsearch.cgiで検索をちょっといい感じに

公開

Movable TypeのユーザーコミュニティであるMTQに、「mt-ftsearch.cgiとは何でしょうか?」という質問がありました。僕も以前からmt-ftsearch.cgiは何だろう?と思っていたので、この機会に調べてみました。

Googleで検索すると、Extensible Search Documentation · movabletype/Documentation Wiki · GitHubの中にFreeTextSearchの項があり、mt-ftsearch.cgiの解説がされていました。さっと読んだ感じでは、MySQLのFULLTEXTインデックスを利用して全文検索を行うシステムのようです。

そこで、昨日インストールしたMroongaも併用して、少しですがmt-ftsearch.cgiのテストを行ってみました。

テストに使うデータ

次の文章を個別に記事として登録しました。このサンプルは、MySQLで高速全文検索を実現するMroongaでTokenMeCabが使えないときの対処方法に掲載されていました。(TokenMeCabが使えなかったわけではありません。)

  • 明日の東京都の天気は晴れでしょう。
  • 明日の京都の天気は雨でしょう。

検索ワードは「京都」を利用します。

mt-search.cgiを利用して検索した場合

mt-search.cgiは、MTで通常利用される検索プログラムです。

「京都」で検索すると、テスト用に登録した記事が2件とも表示されました。「東京都」にも「京都」が含まれるためです。

mt-search.cgiにて「京都」で検索した場合の結果画面

MySQLに発行したクエリを見てみると、次のようにLIKEを利用したクエリになっています。

SELECT entry_id
FROM mt_entry
WHERE ((entry_status = '2' AND entry_blog_id IN ('1')) AND (((entry_keywords LIKE '%京都%') OR (entry_text LIKE '%京都%') OR (entry_text_more LIKE '%京都%') OR (entry_title LIKE '%京都%'))))
ORDER BY entry_authored_on DESC, entry_id ASC
LIMIT 10

mt-ftsearch.cgiを利用して検索した場合

「京都」で検索すると、テスト用に登録した記事2件の内、「京都」の方だけ表示されました。こちらの方がいい感じですね。

mt-ftsearch.cgiにて「京都」で検索した場合の結果画面

MySQLに発行したクエリを見てみると、次のようにMATCH() ... AGAINSTを利用したクエリになっています。

SELECT entry_id, entry_text
FROM mt_entry
WHERE ((entry_status = '2' AND entry_blog_id IN ('1'))) AND ((MATCH(entry_keywords, entry_text, entry_text_more, entry_title) AGAINST('京都' IN BOOLEAN MODE)))
ORDER BY entry_authored_on DESC, entry_id ASC
LIMIT 10

mt-ftsearch.cgiを使う際の準備

mt-ftsearch.cgiを使うには、ドキュメントにあるようにmt_entryテーブルにMySQLのFULLTEXTインデックスを作成する必要があります。FULLTEXTインデックスは、次のコードで作成できます。

CREATE FULLTEXT INDEX mt_entry_fulltext_index ON mt_entry (entry_keywords, entry_text,entry_text_more, entry_title);

ただ、日本語・中国語・韓国語の場合、" " (スペース), "," (カンマ), and "." (ピリオド)で文章が区切られないため、形態素解析を行う必要があります。そこで、Mroongaの力を借ります。

今回は、mt_entryテーブルでMroongaのラッパーモードを利用するようにします。
テーブルのコメント・ストレージエンジンの設定状況

さらにmt_entry_fulltext_indexインデックスでは形態素解析にMeCabを利用するように設定しました。
インデックスの設定状況

詳細な説明をするととても長くなるのと上手く説明する自信が無いので、今日はこの位にしておきます。

まとめ

mt-ftsearch.cgiを使うと、検索結果がちょっといい感じになることが分かりました。(もちろん検索ワードにもよります。)速さを比較することがまだできていないのですが、ドキュメントにもあるようにいくつかのフィールドにLIKEで検索をするよりは速そうです。ただし、MySQLにINSERTが発行される場合...記事を登録する時などは、FULLTEXTインデックスを作成しない場合に比べて動作が遅くなるようそうです。

本ブログはPSGIでMTを動作させているので、近いうちにmt-ftsearch.cgiを導入して全文検索を試してみたいと思います。検索スコアも使えるとよいのですが...。

余談ですが、Wordpressa-blog cmsconcreate5で試してみたところ、mt-search.cgiと同様の結果(「京都」で検索すると「東京都」も引っかかる)になりました。日本語でFULLTEXTインデックスを使うにはなかなか大変ですからね。