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)だけでも実現できるとかなり嬉しいなぁと考えています。 お手数ですがご検討願いますでしょうか?