全文検索エンジンGroongaでサジェスト機能用のコマンドラインツールを使ってみる


[gihyo.jp](http://gihyo.jp/)さんでGroongaの隔週連載が最終回を迎えました。Groongaの最新情報と今後に興味があれば一読をおすすめします。該当記事は[「最終回　Groongaの今と未来」](http://gihyo.jp/dev/clip/01/groonga/0011) です。

第1回から第10回までの過去記事については、[隔週連載Groonga](http://gihyo.jp/dev/clip/01/groonga)のページを参照してください。

今年も11/29に[全文検索エンジンGroongaを囲む夕べ 4](http://atnd.org/events/43461)を開催することになりました。Groongaのいろんな話を聞きたい人にはおすすめです。すでに参加希望者が100名を超えました！まだ余裕はありますが参加登録はお早めに! 発表者も決まったので[タイムテーブル](http://atnd.org/events/43461#time-table)に反映しました！

# はじめに

オープンソースの[カラムストア機能付き全文検索エンジンGroonga](http://groonga.org/ja/)を公開しています。この記事を書いた時の最新のバージョンは2013年10月29日にリリースした[3.0.9](http://groonga.org/ja/docs/news.html#release-3-0-9)です。

前々回は、Groongaで[サジェスト機能](http://groonga.org/ja/docs/suggest.html)を利用するときの具体例のうち、補完について紹介しました。
前回は、引き続きサジェスト機能のうち、補正について紹介しました。

* [全文検索エンジンGroongaでサジェスト機能(補完)を使ってみる](http://qiita.com/groonga/items/891ceade90ca45df6462)
* [全文検索エンジンGroongaでサジェスト機能(補正)を使ってみる](http://qiita.com/groonga/items/97ac93a083bea0b3527b)

今回は、これらサジェスト機能に関係したコマンドラインツールである、groonga-suggest-httpdとgroonga-suggest-learnerについて紹介します。

# Groongaのサジェスト機能とは

前々回、前回のエントリでサジェスト機能について紹介しましたが、再度おさらいしておきましょう。
全文検索エンジンGroongaの特徴のひとつに、サジェスト機能があります。
このサジェスト機能では、補完、補正、提案ができるようになっています。

* [補完](http://groonga.org/ja/docs/suggest/introduction.html#completion)
* [補正](http://groonga.org/ja/docs/suggest/introduction.html#correction)
* [提案](http://groonga.org/ja/docs/suggest/introduction.html#suggestion)

補完は一部の入力をもとにして、登録済みの語の中から補完候補の語を返します。補正は誤入力をもとにして、登録済みの補正ペア(誤入力に対応した正しい入力のペア)から補正された語を返します。提案は入力をもとにして、登録済みの関連クエリペア(キーワードとそれに関連するクエリのペア)から追加のキーワードを含む新しいクエリを返します。

サジェスト機能の個別の機能についてはドキュメントに簡単な例がありますが、一連の流れをまとめて説明しているわけではないのでちょっとわかりにくいかもしれません。

[チュートリアル](http://groonga.org/ja/docs/suggest/tutorial.html)のセクションも用意していますが、まだTODOという状態で空っぽです。

提案機能を使った具体例としては[Groonga 3.0.3のリリースアナウンス](http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-April/001337.html)で「学習時の重み付けのカスタマイズをサポート」というトピックがあるので、それが参考になるかもしれません。

上記の状況に加え、サジェスト機能に関連したコマンドラインツールにgroonga-suggest-httpdとgroonga-suggest-learnerというものがあるのですが、ドキュメントの整備はこれからです。

そこで、今回はそれら2つのコマンドラインツールについて紹介してみます。

* groonga-suggest-httpd
* groonga-suggest-learner

## groonga-suggest-httpdとは

groonga-suggest-httpdはGroongaのサジェスト機能を使うにあたっての学習用のログを準備するのに便利なコマンドラインツールです。

groonga-suggest-httpd単体でも使えますし、後述するgroonga-suggest-learnerに生成したログを指定して学習させることもできます。

どんなオプションが指定できるかオプションを見てみましょう。

```
% groonga-suggest-httpd
Usage: groonga-suggest-httpd [options...] db_path
db_path:
  specify groonga database path which is used for suggestion.

options:
  -p, --port <port number>                  : http server port number
                                              (default: 8080)
  -c <thread number>                        : number of server threads
                                              (deprecated. use --n-threads)
  -t, --n-threads <thread number>           : number of server threads
                                              (default: 8)
  -s, --send-endpoint <send endpoint>       : send endpoint
                                              (ex. tcp://example.com:1234)
  -r, --receive-endpoint <receive endpoint> : receive endpoint
                                              (ex. tcp://example.com:1235)
  -l, --log-base-path <path prefix>         : log path prefix
  --n-lines-per-log-file <lines number>     : number of lines in a log file
                                              use 0 for disabling this
                                              (default: 1000000)
  -d, --daemon                              : daemonize
  --disable-max-fd-check                    : disable max FD check on start
  -h, --help                                : show this message
```

``-s`` や ``-r`` はgroonga-suggest-learnerと連携して使うときに指定します。
groonga-suggest-httpd単体で使用するときには必要ありません。

では実際に使ってみましょう。

サンプルデータとしては[全文検索エンジンGroongaでサジェスト機能(補完)を使ってみる](http://qiita.com/groonga/items/891ceade90ca45df6462)で使っていたものを使いましょう。

```
% rm -fr testdb
% mkdir -p testdb
% groonga-suggest-create-dataset testdb/db rurema
% groonga testdb/db < items.grn
% groonga testdb/db < learn.grn
```

ここまでで、ひとまずベースとなる学習まで終わりました。

では、groonga-suggest-httpdを起動してみます。
ログを保存するディレクトリもあらかじめ作成しておきます。

```
% mkdir -p logs
% groonga-suggest-httpd -l logs/log --n-threads 1 testdb/db
```

実行するとコマンドラインプロンプトは待機状態になります。デーモンとして起動したい場合には ``-d``を指定します。

groonga-suggest-httpdを起動したら、次は補完してみましょう。

groonga-suggest-httpdは標準では8080番ポートでリクエストを待ち受けています。
そこで、curlコマンドを使って補完を試してみます。

リクエスト時のパラメータは次のものを指定します。

|キー|説明|
|---|----|
|q|ユーザがフォームに入力したクエリ文字列(UTF-8)を指定します。|
|t|クエリ種別を指定します。クエリ種別とはcomplete, correct, suggest, submitのうちいずれかの値です。もしくはsubmit を除いた 3 つのうち任意個を「|」で連結した値を指定します。|
|n|suggest結果の計算元となるデータセット名を指定します。|
|l|学習の対象となるデータセット名を指定します。もしくは、任意個のデータセット名を「|」で連結した値を指定します。|

「配」一文字で補完を試してみるには次のようなリクエストを実行します。

```
curl "http://localhost:8080/?q=%e9%85%8d&t=complete&n=rurema&l=rurema&h=0"
```

補完結果として「配列」が返って来ました。これは期待通りですね。

```
{"complete":[[1],[["_key","ShortText"],["_score","Int32"]],["配列",5]]}
```

キーとして``callback``を指定するとjsonpを取得することができます。

```
curl "http://localhost:8080/?q=%e9%85%8d&t=complete&n=rurema&l=rurema&h=0&callback=jsonp_func"
```

補完結果としてJSONPで「配列」が返って来ました。これも期待通りですね。

```
jsonp_func({"complete":[[1],[["_key","ShortText"],["_score","Int32"]],["配列",5]]});
```

次は、「dro」で補完を試してみましょう。

```
curl "http://localhost:8080/?q=dro&t=complete&n=rurema&l=rurema&h=0"
```

まだ「dro」で「droonga」と補完するための学習をしていないので、当然補完候補もなく0件です。

```
{"complete":[[0],[["_key","ShortText"],["_score","Int32"]]]}
```

## groonga-suggest-httpdで学習用のログを用意する

では、学習用のログデータを用意しましょう。

学習させるときには、リクエストに追加のパラメータが必要なので忘れないようにしましょう。

|キー|説明|
|---|----|
|i|ユーザーを識別するためのID文字列を指定します。|
|s|1970年1月1日午前0時からの経過時間 (ミリ秒) を指定します。|

例えば、「droonga」を学習させるためのリクエストとして次のようなクエリを実行します。

```
curl "http://localhost:8080/?q=droonga&t=submit&n=rurema&l=rurema&h=0&i=192.168.1.29&s=1383206729610"
```

何度かsubmitでいろんなデータを学習させてみてください。

ここまでで、logs以下のディレクトリを確認してみましょう。

```
% la logs
合計 32K
-rw-rw-r-- 1 kenhys kenhys 29K 10月 31 17:46 log20131031173700-00
```

logというプレフィクスのついたファイルが生成されていることがわかります。
リクエストを実行することで学習させるためのクエリデータがログとして蓄積されていきます。
ログへの書き込みは、即座に反映されるわけではないことに注意してください。

実際のログには次のような内容が記録されているはずです。

```
/?q=dro&t=complete&n=rurema&l=rurema&h=0&i=192.168.1.29&s=1383206729601
/?q=droong&t=complete&n=rurema&l=rurema&h=0&i=192.168.1.29&s=1383206729602
/?q=droonga&t=submit&n=rurema&l=rurema&h=0&i=192.168.1.29&s=1383206729609
```

これで、学習用のログの準備ができました。

## groonga-suggest-learnerとは

groonga-suggest-httpdが生成するログから学習させるためのツールがgroonga-suggest-learnerです。

こちらもオプションを確認してみましょう。

```
% groonga-suggest-learner 
Usage: groonga-suggest-learner [options...] db_path
options:
  -r <recv endpoint>: recv endpoint (default: tcp://*:1234)
  -s <send endpoint>: send endpoint (default: tcp://*:1235)
  -l <log directory>: load from log files made on webserver.
  -d                : daemonize
```

groonga-suggest-httpdと連携して動作させることもできますが、こちらも単体で実行することができます。
そのため、ログをもとに学習のみ実行するということができます。

先程用意したログを使って学習させてみましょう。

```
% groonga-suggest-learner -l logs testdb/db
```

もし、ログのクエリデータ必要なパラメータが不足している場合には警告メッセージが表示されます。
そのときは、リクエストを確認してください。

```
% groonga-suggest-learner -l logs testdb/db
invalid line path:logs/log20131031173700-00 line:1
invalid line path:logs/log20131031173700-00 line:2
invalid line path:logs/log20131031173700-00 line:3
invalid line path:logs/log20131031173700-00 line:4
```

では、groonga-suggest-learnerで学習できたら、学習できたか確認してみましょう。

確認するには次のようなクエリを実行します。「dro」から補完できるでしょうか。

```
curl "http://localhost:8080/?q=dro&t=complete&n=rurema&l=rurema&h=0"
```

きちんと「dro」で「droonga」が補完されました。

```
{"complete":[[1],[["_key","ShortText"],["_score","Int32"]],["droonga",41]]}
```

# まとめ

今回は、全文検索エンジンGroongaのサジェスト機能のためのコマンドラインツールを2つ紹介しました。

まだチュートリアル等が充実していないので、とっつきにくかったサジェスト機能の参考になったでしょうか。

Groongaに興味を持ったなら、まずは[インストール](http://groonga.org/ja/docs/install.html)して試してみてください。

Groongaの基本的な動作を知るための[チュートリアル](http://groonga.org/ja/docs/tutorial.html)もあります。インストールしたら試してみてください。