[groonga-dev,02637] [相談]トークナイザープラグインのためのgrn_token周りの処理について

アーカイブの一覧に戻る

Naoya Murakami visio****@gmail*****
2014年 8月 15日 (金) 09:23:54 JST


村上です。

トークナイザープラグインを作ろうと考えているのですが、もう少し
トークナイザー側に情報を渡していただけると色々と便利なのになぁ、
と思っています。

ちょっと長文になりますが相談させてください。

現在、トークナイザー側に渡されている情報は、以下の3つだけだと思います。

str_:トークナイズ対象の文字列
flags_:GRN_TOKEN_ENABLE_TOKENIZED_DELIMITERのケースのみ
table:語彙表のテーブル

https://github.com/groonga/groonga/blob/master/lib/token.c#L532-L536

(1)grn_token_mode(GRN_TOKEN_GET/GRN_TOKEN_ADD)をトークナイザー側
で参照できるようにしたいです。

これができればインデックス作成時(GRN_TOKEN_ADD)とインデックス参照
時(GRN_TOKEN_GET)でトークナイズ処理を切りかえることができます。

現在、Ngramトークナイザーでは検索時のみオーバーラップありで長さが
NgramのNに満たないもの(UNMATURED)のトークンを飛ばしていると思います。
1文字トークンは末尾を検索する以外の場合は必要ないためだと思います。

https://github.com/groonga/groonga/blob/master/lib/token.c#L599-L601

たとえば、TokenBigramでは以下のようにトークナイズされています。

トークナイズ対象「今日は雨です」
GRN_TOKEN_ADD:「今日:0/日は:1/は雨:2/雨で:3/です:4/す:5」
GRN_TOKEN_GET:「今日:0/日は:1/は雨:2/雨で:3/です:4」

これをトークナイザープラグインで、
GRN_TOKEN_ADD:「今日:0/日は:1/は雨:2/雨で:3/です:4/す:5」
GRN_TOKEN_GET:「今日:0/は雨:2/です:4」
こうなるようにしたいと考えています。

Ngramでは単語境界がわからないので、インデックス作成時では
オーバラップが必要ですが、検索時はオーバラップさせる必要
がないような気がしています。こうすればpostingの比較回数が
減り高速化につながるんじゃないかなぁと思っています。
(考慮漏れのケースがあるかもしれませんが。。)

このほか、語彙表のキーに紐付けてストップワードフラグとかを設ければ、
検索時のみ所定のストップワードを飛ばす、といったこともできそうです。

・実現方法案
最低限、以下のようにmodeをctxにpushしていただければ、トークナイザー側
でmodeを判定することができます。
statusをGRN_TOKENIZER_TOKEN_UNMATUREDとGRN_TOKENIZER_TOKEN_OVERLAPにすれば、
GRN_TOKEN_GETの場合のみトークンをスキップしてpositionを進めることができます。

[commit1]
token: push grn_token_mode to grn_ctx for tokenizer
https://github.com/naoa/groonga/commit/7fc86773660c2ee72c3efd44388e84d2f25c7e1e

(2)ただ、1. のステータスでスキップさせる方法だと意味合いがよくわ
からなくなるので、可能であれば以下のようなTOKENのスキップステータス
を追加していただければさらに嬉しいです。

#define GRN_TOKENIZER_TOKEN_SKIP (0x01L<<4)

意味:トークンをスキップさせます。(positionは進めます)
用途:トークンのマッチング対象を絞り込むことができます。
例:「今日は雨です」→「今日:0/は雨:2/です:4」
(「日は」,「雨で」のトークンをスキップし、positionは進める。)
効果:転置索引の容量は減らせませんが、検索を高速化できます。

[commit2]
token: add tokenizer token skip
https://github.com/naoa/groonga/commit/c5ec116da1c3276ea2a39c6581eeeabea49d9f01

(3)さらに、POSITIONのスキップフラグも追加していただけると、トークン
フィルターも簡単に実現できるようになって最高です。
(現状、トークナイザー側でトークンを飛ばそうと考えると、最後のトー
クン以外であればトークナイザーのなかでループさせることで実現できます
が、最後のトークンでフィルターさせるとwarningになってしまうので先読
みが必要かなぁとかかなりカオスだったり。。)

#define GRN_TOKENIZER_TOKEN_WITH_POSITION_SKIP (0x01L<<5)

意味:トークンとpostionをスキップさせます。
用途:トークンフィルターに使うことができます。
例:「今日は雨です」→「今日:0/雨:1/です:2」
(「は」のトークンをスキップし、positionは進めない)
効果:検索できないケースが増える代わりに転置索引の容量を減らすことができ、
検索を高速化することができます。

[commit3]
token: add tokenizer token postion skip
https://github.com/naoa/groonga/commit/26e93c27ab158020fe24426ab05a05fb779c0b39

現状のGroongaであまり触りたくないところかもしれませんが、せめて、
(1)だけでも実現できるとかなり嬉しいなぁと考えています。

お手数ですがご検討願いますでしょうか?



groonga-dev メーリングリストの案内
アーカイブの一覧に戻る