MeCab を使ってフォームに自前のサジェスト(自動補完)やオートコンプリートを実装する方法

自前のキーワード一覧からサジェストを実装するにあたり色々調べたのですが、これだ!という記事はほとんど無かったですね。「jQuery UI の Autocomplete」や「Google サジェスト」あたりを使った事例は多かったですが…。まぁ、ある程度納得のいく機能を自分で作れたので紹介します。なお、以下の記事は非常に参考になりました。

特にNaverまとめのエンジニアブログは非常に参考になったというか、今回はそれを簡潔にリライトしたような話になります。なぜこんな良い記事を消してしまったのか…。

細かい話は上記の参考記事を読んでもらうとして、上の動画っぽいことを実現するには、

  1. 「MeCab」と、その辞書 mecab-ipadic-NEologd をサーバにインストールしておく
  2. サジェスト用のデータベースを作成し、「キーワード」と「ローマ字読み」を保存
  3. フォームの内容をajax等でサーバに送信、サーバ側でローマ字に変換しDB内を検索

これだけです。個人的にはGoogle検索に近い印象になったので、満足していますね。

1. MeCab と mecab-ipadic-NEologd をインストール

ググれば出てくるので割合。基本的には mecab-ipadic-NEologd は必須かと思います。

2. サジェスト用のデータベースを作成し、「キーワード」と「ローマ字読み」を保存

例えばこんな感じでテーブルを作成します。私は高速化のために全文検索の Mroonga を使っていますが趣旨がズレてしまうので、必要に応じて InnoDB とかに変更して下さい。

CREATE TABLE `suggest_keyword` (
  `keyword` varchar(255) PRIMARY KEY,
  `roman` varchar(255) DEFAULT NULL,
   FULLTEXT INDEX (roman)
) ENGINE=Mroonga DEFAULT CHARSET=utf8;

あとは、keywordにサジェストそのものを、roman にローマ字読みをinsertしていきます。例えば「東京」を「toukyou」にするまでの手順としては、以下の通りです。

「東京」を Mecab に投げる。コマンドラインでの利用はもちろん、
PHPで利用することも可能です。私は以下を元に関数化しています。
<http://d.hatena.ne.jp/toku-hiro/20090121>
↓
「東京 名詞,固有名詞,地域,一般,*,*,東京,トウキョウ,トーキョー」
みたいなのが返ってくるので、「トウキョウ」の部分を拾っておく
↓
カタカナをローマ字書きに変換する(toukyou)。
PHPの場合は、以下を参考にすると良いでしょう。
<http://php-archive.net/php/romaji/>
↓
INSERT INTO `suggest_keyword` (`keyword`, `roman`) VALUES ('東京', 'toukyou');

3. フォームの内容をajax等でサーバに送信、サーバ側でローマ字に変換しDB内を検索

ここまできたら、フロントエンドも同じようなことをするだけですが一応。

----------------
▼html
----------------
<input id="keyword" type="text" value="" autocomplete="off">
<ul id="suggest" style="display:none"></ul>

----------------
▼JQuery
----------------
$('#keyword').on('focus keyup', function () {
    $.ajax({
        type: "POST",
        dataType: 'json',
        url: '【自前サジェスト用APIのURL】',
        data: {
            q:$(this).val()
        }
    }).done(function(e){
        // サジェスト一覧が返ってきたら #suggest にappendするなどの処理
    });
}).on('blur', function () {
    // フォーカスが外れたら #suggest を初期化するなどの処理
});

【自前サジェスト用APIのURL】は、サジェスト用データベースの準備の時と一緒。POSTで送った #keyword の入力データをMecabに投げて、返ってきた読み(カタカナ)をローマ字書きにしたものを roman から検索。JSON形式で返却すればOKかと思います。

自前サジェストを作る流れ

サーバ側のコードについては整理できておらずお見せ出来なくて残念ですが、この流れが理解できたら、ちょっとプログラミングかじってる程度の人なら実装できるでしょう。

念のため説明しておくと、サジェストは文字を書いている途中でも出力されるようにしたいので、ローマ字読みを保存することは必須になります。例えば「東京」と入力する場合、「とうk」「トウk」「とうきょ」などが入力途中に書かれそうです。

これを全てローマ字に変換し、全文検索やらLIKEやら使ってDBのローマ字読み部分へ検索かければサジェスト機能を実現できます。「そんな簡単にいかんでしょ」と思うかもしれませんが、Mecab と mecab-ipadic-NEologd を使うことで、簡単に実現できます。

MeCabは簡単に言うとIME辞書みたいなもので、「東京」を「とうきょう」のような形に変換してくれるものです。ただ、例えば北海道に「ニセコ町(nisekocho)」という町があるんですが、標準では登録されておらず「ニセコマチ(nisekomachi)」になります。

これだと正しいローマ字読みになりません。ところが、mecab-ipadic-NEologd という辞書を使うことで解決できます。登録されている単語数が多く、市区町村は楽勝でした。

注意点はもう一つあり、ローマ字については書き方が複数ありますよね。例えば「ジ」と書く際、「zi」でも「ji」でもいけちゃいます。なのでそのままだと少し不親切です。そこで、直接ローマ字読みを入れず、一旦ひらがな(カタカナ)に変換してからローマ字へ変換する(フォーマットは統一する)のが最も安全なのかなぁと考えています。