MySQL フレーズ検索で日本語全文検索をLightに。
MySQLのFullText Index(全文Index)を使うと、全文検索をライトにできます。
Solrや、Triton,Senner,Groongaに比べて、機能的には劣りますが、MySQLだけでできますので、
Hard,MiddleWare的にもLightだと思います。サーバー数台でやってるような小さいWebサービスで、
ちょっと全文検索いれたい!みたいな時にはぴったりです。
でも、ちょっと工夫しなくてはいけない点があります。
現時点(MySQLVer5.5)では、
FullTextIndexがサポートされているデータベースエンジンはMyISAMのみで、
スペースで区切られているような言語しかサポートされていないということ。
つまり、日本語で使用したいときは、Ngramか、形態素解析して、単語に区切らないとそのままでは使えません。
その辺のことは下記を参照してください。
MySQL を使った全文検索 (Full-Text Search)
http://www.nilab.info/zurazure2/000319.htmlMySQLで全文検索 - FULLTEXTインデックスの基礎知識
http://www.tatamilab.jp/rnd/archives/000389.html#i本家リファレンス
http://dev.mysql.com/doc/refman/5.1/ja/fulltext-search.html
MySQLのFulltext Indexを日本語対応する際の解決策は2つです。
- アプリケーション側でNgram化か形態素解析して単語をスペース区切りにする
- Fulltext Paser PluginというPlugin(MySQL5.1のみ)を使用する (http://sourceforge.net/projects/mysqlftppc/ ※BigramやmecabのPluginがあります)
私は、MySQL5.5を使用していて、現時点のFulltext Parser Pluginで、サポートしているものがないので、
アプリケーション側でNgram化して、MySQLのFulltext Indexを使用しています。
さらに、Boolean Modeのフレーズ検索で正しい日本語検索を行ないます。
アプリケーション側で全文検索する際は、検索クエリもNgram化しますが、その際にフレーズ検索を使用しないと、
検索してしまいます。
例えば、「ビズリーチ」をBigramした場合、「ビズ ズリ リー ーチ」となり、SQL的には、下記のようなクエリとなります。
select * from table_name where match(column_name) against('+ビズ +ズリ +リー +ーチ' in boolean mode);
しかし、これでは「ビズリーチ」ではないが、「ビズ ズリ リー ーチ」をすべて含む文章が引っかかってしまいます。
正しく日本語検索したい場合はフレーズ検索を利用します。
select * from table_name where match(column_name) against('+"ビズ ズリ リー ーチ"' in boolean mode);
こうすると、正しく「ビズリーチ」のみ検索できます。
本家リファレンス(Boolean Mode フレーズ検索はリンクの一番下に書いてあります)
http://dev.mysql.com/doc/refman/5.1/ja/fulltext-boolean.html
また、複雑なWhere句や、ネストを含む複雑なSQLにすると、すぐにFulltextIndexを使ってくれないSQLとなり、遅くなります。
And検索の場合は、横に並べる、OR検索の場合は、Unionをします。
例えば、「(ビズリーチ and ルクサ) or はてぶ」の場合は、下記のようなSQLにすると、FulltextIndexが必ず使用されます。
select * from table_name where match(column_name) against('+"ビズ ズリ リー ーチ" +"ルク クサ"' in boolean mode); union select * from table_name where match(column_name) against('+"はて てぶ"' in boolean mode);
なぜか、MySQLに関するエントリーが多い。次はアプリ側のことをもっと書こうかな。