mysql+mroongaで全文検索
DESCRIPTION
「MySQL勉強会 in 大阪(第6回)」 http://atnd.org/events/49005 で、あかやまさんに発表頂いた時の資料です。TRANSCRIPT
MySQL + Mroongaで全文検索 あかやま
自己紹介
SE会社でSEとして勤務しています。
主に、お客様の社内、社外ポータルサイトの開発をメインに行っています。
3年前より、MySQLを使ったシステム開発をするようになりました。(MySQL5.5~)
それまでは、OracleとかPostgreSQLを使ったシステム開発がメインです。
MySQLやMroongaのエキスパートではありません。
きっかけ
あるWEBサイトのリプレイスを担当することになりました。概要は、
• あるコンテンツを大分類、中分類などのジャンル別に登録して利用者へ表示させる。
• フリーワード検索機能も提供したい。当然、ひらがな、かたかな、全角、半角の違いは吸収してほしい。
• データの登録は、サイト運営者のみが行い。利用者からの投稿機能はない。
ちなみに現行システムは
• データベースは、PostgreSQLを利用。
• フリーワード検索機能も提供しているが、like検索を行っている。
「パズル」で検索しないと、「パズル&ドラゴンズ」はヒットしない。
検索対象カラムは、画面表示用のカラム と あいうえお順にソートするため ふりがな のカラムが存在している。
データ件数は 1000 件程度。 今後は、もっと増える予定。
要件にあったものを探しましょう
フリーワード検索といえば
• Solr が有名なんだけど…
開発経験なし。 決められたスケジュール、予算では難しい。
データの移行も大変そう。
RDBにも全文検索という機能があるよね…
• Oracle … 予算の都合でNG(そもそも現行システムはPostgreSQLだし。)
• PostgreSQL
Senna → サイトが2010年以降更新されている様子もなし。ちょっと不安。
pg_bigram → なんか使えそう。 でも、要件にある ひらがな、カタカナ、全角、半角を吸収する方法は?
• MySQL
mroonga → 毎月、リリースがあり活発に活動されている。
collation の設定でひらがな、カタカナ、全角、半角を吸収できる。
MySQL + mroonga を使うことに決定。
Mroonga とは、 (http://mroonga.org/ja/ より)
GroongaをベースとしたMySQLのストレージエンジン
Groonga独自のカラムストアを持つ列指向のデータベース
Tritonnの後継 (MySQLに全文検索ライブラリSennaを組み込んだもの)
MySQLのプラグインとして動作
MySQL公式バイナリに手を加えずにプラグインとして動的にロードして利用可能
2つの動作モードをサポート
ストレージモード
デフォルトモード。データストア、検索機能もすべてGroongaを使うモード。ただし、トランザクションなどの機能はなし
ラッパーモード
MyISAMやInnoDBに全文検索機能だけを追加するモード。
形態素解析、N-gram、空白区切り などのパーサーが用意されている。
さっそく試してみましょう
環境 ※昨年のことのなので、情報は古いです。
• OSは、CentOS6、 mroonga のバージョンは、3.0.7
• Mroonga のサイトで配布されるパッケージは、MySQLのバージョンは5.1に対応したもののが配布されていました。 5.1はあまりにも古いし、UTF8の4バイト文字に対応していなので MySQL5.6 の組み合わせでソースからインストールすることに決定。
インストール
Mroongaのサイトをにあるインストール手順を参照し、必要なものを集めてインストール。
• mecab ・・・ 形態素解析で必要。
• Groonga ・・・ groongaのサイトのインストール手順を参照。
• MySQL ・・・ cmakeのオプションを確認しながら。英語なので悪戦苦闘。
• Mroonga ・・・ mroongaのサイトのインストール手順を参照。
• Groongaノーマライザー ・・・ groongaのサイトのインストール手順を参照。
※MySQL以外はインストール手順書が日本語だったのですんなりできました。 :-p
さっそく試しみましょう
以下のようなテーブルを作ってみました。 (ラッパーモードの場合)
mysql> CREATE TABLE contents (
-> id INT PRIMARY KEY AUTO_INCREMENT,
-> title VARCHAR(255),
-> kana VARCHAR(255),
-> FULLTEXT INDEX (kana) COMMENT 'parser "TokenBigram"'
-> ) ENGINE = mroonga COMMENT = 'engine "innodb"' DEFAULT CHARSET utf8mb4 COLLATE=utf8mb4_unicode_ci;
mysql> INSERT INTO contents (title,kana) VALUES ("牛肉","ぎゅうにく");
mysql> INSERT INTO contents (title,kana) VALUES ("豚肉","ぶたにく");
mysql> INSERT INTO contents (title,kana) VALUES ("牛乳","ぎゅうにゅう");
mysql> INSERT INTO contents (title,kana) VALUES ("筍","たけのこ");
mysql> INSERT INTO contents (title,kana) VALUES ("数の子","かずのこ");
mysql> select * from contents;
+----+--------+--------------------+
| id | title | kana |
+----+--------+--------------------+
| 1 | 牛肉 | ぎゅうにく |
| 2 | 豚肉 | ぶたにく |
| 3 | 牛乳 | ぎゅうにゅう |
+----+--------+--------------------+
コメントでパーサを指定する
ENGINE は mroongaを
COMMENTでMySQLのエンジンを指定する。
COMMENTを指定しなかった場合は、
ストレージモードでテーブルが作成される。
さっそく試しみましょう 検索結果
mysql> SELECT * FROM contents WHERE MATCH(kana) AGAINST("ぎゅう");
+----+--------+--------------------+
| id | title | kana |
+----+--------+--------------------+
| 1 | 牛肉 | ぎゅうにく |
| 3 | 牛乳 | ぎゅうにゅう |
+----+--------+--------------------+
2 rows in set (0.02 sec)
mysql>
mysql> SELECT * FROM contents WHERE MATCH(kana) AGAINST("ニク");
+----+--------+-----------------+
| id | title | kana |
+----+--------+-----------------+
| 1 | 牛肉 | ぎゅうにく |
| 2 | 豚肉 | ぶたにく |
+----+--------+-----------------+
2 rows in set (0.02 sec)
• 期待どおりの検索結果がでました。 ひらがな、かたかな が同一視されているのは MySQLのCOLLATEの設定が効いているためです。
• フリーワード検索なので、漢字が入力されることもあります。その場合の対応として mecab で漢字→かな変換をしています
さっそく試しみましょう と思ったのですが。。。
mysql> SELECT * FROM contents WHERE MATCH(kana) AGAINST("タケノコ");
+----+-----------+--------------+
| id | title | kana |
+----+-----------+--------------+
| 4 | 筍 | たけのこ |
| 5 | 数の子 | かずのこ |
+----+-----------+--------------+
2 rows in set (0.02 sec)
• MySQLのリファレンスマニュアルでブール全文検索を参照。
(英語はしんどいので、5.6のマニュアルと5.1の日本語のマニュアルを並べてみる。)
mysql> SELECT * FROM contents WHERE MATCH(kana) AGAINST("タケノコ" IN BOOLEAN MODE);
+----+-------+--------------+
| id | title | kana |
+----+-------+--------------+
| 4 | 筍 | たけのこ |
+----+-------+--------------+
2 rows in set (0.02 sec)
trigram にしたら、「かずのこ」はヒットしなくなりましたが。 じゃ「きゅうり」と「ぎゅうにく」は?
感想
はじめて使った見たのですが、インストールからDBの構築までは、はまることなくできました。
また、MySQLのプラグインとして動作するものなので、だめだったら使わなければいいという
気持ちで使い始めました。
利用するシーンとしては、今まで like検索していたもの、(商品名、人名)で遅いといわれた場合に
導入してみるのもいいかなぁと思います。
ただ、実際のシステムは、ここでご紹介したような単純なものではなかったので、ノイズが多くて
こまりました。(検索結果として出てほしくないものがでたり、でてほしいものがでないなど)
日本語って難しいですね。
その時も、ここでは紹介していない パーサーをつかってみたり、Groongaのトークナイザを使ったり
して乗り切ることができました。(細かいところまで手がとどく)
参考サイト、ツール紹介
ツール
• MySQL Workbench ( http://dev.mysql.com/downloads/tools/workbench/ )
何かと便利。ちょっと重いかな?
• A5:SQL Mk-2 ( http://www.wind.sannet.ne.jp/m_matsu/developer/a5m2/ )
ER図の作成だけではなく、ER図のリバース生成ができます。
今回は、旧システムのデータベースの構成を確認するために、大活躍しました。
参考サイト
• gihyo.jp ( http://gihyo.jp/dev/clip/01/groonga/0001 )
2013年4月~2013年9月 連載記事がありました。
• Qiita ( http://qiita.com/tags/mroonga )