Kouhei Sutou
kou****@clear*****
2014年 8月 13日 (水) 19:01:17 JST
須藤です。 In <CANM+****@mail*****> "[groonga-dev,02611] Re: [mroonga] asterisk wildcard operator" on Wed, 13 Aug 2014 06:47:52 +0900, Naoya Murakami <visio****@gmail*****> wrote: > 本件なんですが、Groongaで以下のようなnear関数を追加することにより、文字数を > 指定した近傍検索ができるようになりました。 > > https://github.com/naoa/groonga-function-near おぉ! GRN_OP_NEARの使い方はこれであっています! grn_column_index()にはGRN_OP_MATCHではなくGRN_OP_NEARを指定 してください。GRN_OP_NEAR用のインデックスを探したいので。 ちなみに、func_near()の実装は、Groonga本体に入っている sub_filter関数やquery関数(selectの引数じゃなくqueryという関 数)の実装と同じようにするのがよいです。 > (このプラグインはgrn_proc_set_selectorのAPIが公開されているのが前提です。) 取り込みました! > そこで、Mroongaから使うことを想定して、Groonga本体にnear関数を実装したいと > 考えているのですが、いかがでしょうか? すばらしいと思います! > Groongaのnear関数を実装した上で、TritonnのN[数値]"文字列"の演算子 > (これはNプラグマっていうんですかね?)相当の処理をMroongaに実装を > してみたいと考えています。 > > http://qwik.jp/senna/query.html よいアプローチだと思います。 が、これはプラグマじゃなくて演算子ですね。 クエリーの先頭ではなく、 AGAINST('ちょっと一杯 *N\"シメ ラーメン\"' IN BOOLEAN MODE) みたいに検索後の最初にくっつけるので演算子です。 > Mroongaから使おうと考えると、Groongaのnear関数には、たぶん、(betweenの > ケースを習うと)castを入れたり、引数をまだ改修しないといけないかもしれない > なぁとは思っています。 いやぁ、実は、そうじゃないんですよ。 > たぶん、以下のあたりでkeywordから先頭の演算子とキーワードを取り出して、 > expressionにgrn_expr_appendで関数を組み立ててやれば、なんとかなるん > じゃないかなぁと思っています。 > (あまり、grn_expr_appendの扱いとデバッグの仕方にあまり慣れていないので、 > まだ、Mroonga側で動く処理を試せていませんが。) > > https://github.com/mroonga/mroonga/blob/master/ha_mroonga.cpp#L7788 プラグマじゃないのでここじゃないんです。 クエリーの中身なのでGroonga側でやる必要があります。 コードで言うと、↓をいじるといけるかなぁ、いけないかなぁとい う感じです。 https://github.com/groonga/groonga/blob/master/lib/expr.c#L6059 こんな感じです。 -- diff --git a/lib/expr.c b/lib/expr.c index 702af5a..e7233cc 100644 --- a/lib/expr.c +++ b/lib/expr.c @@ -6057,9 +6057,10 @@ parse_query(grn_ctx *ctx, efs_info *q) break; case GRN_QUERY_PREFIX : - PARSE(GRN_EXPR_TOKEN_MATCH); q->cur++; get_op(q, op, &mode, &option); + GRN_INT32_PUT(ctx, &q->mode_stack, mode); + PARSE(GRN_EXPR_TOKEN_RELATIVE_OP); break; case GRN_QUERY_AND : if (!first_token) { -- が、今の仕組みだとmax_intervalをカスタマイズできないです ねぇ。。。 lib/ecmascript.lemonをいじって文法を拡張しないといけないかも です。 > うまくいくかわかりませんが、よければ、この実装を自分にやらせてください。 お願いします! と言いたいところなんですが、max_intervalまでがんばるのはだい ぶ難易度が高いんですよねぇ。。。 *N"..."というようにmax_intervalは常にデフォルト値なら前述の あたりをいじればいけそうなんですが。。。 ちなみに、max_intervalを対応するためには次のような作業が必要 になると思います。 * efs_infoに1本スタックを増やす。(max_interval用のスタック。) * ecmascript.lemonの https://github.com/groonga/groonga/blob/master/lib/ecmascript.lemon#L46 をいじって、opがGRN_OP_NEARならmax_interval用のスタック からmax_intervalの値を持ってきてgrn_exprにappendする。 * scan_infoにmax_interval用のフィールドを追加する。 * scan_info_buildの中でGRN_OP_NEARのときはgrn_exprからmax_interval をとってきてscan_infoに設定する * grn_table_select_indexの中でscan_infoからmax_intervalを とってきてgrn_search_optargのmax_intervalに設定する あ、なんか、書いたらいけるような気がしてきた。 けど、grn_exprまわりを知らないと結構ツライと思います。 scan_info_buildあたりが。。。 あぁ、ecmascript.lemonをいじるときにGRN_OP_NEARなら GRN_OP_CALLを積んでnear関数を呼び出すようにすればそれ以降の scan_info云々のやつはやらなくてよくなりますね。そっちのほう がいいかも。 > 自分の用途としてはGroongaのプラグインで動くだけでもいいので、だめなら、APIを > 公開していただくだけでもいいです。 こっちは取り込んだので大丈夫です! -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> Groongaベースの全文検索システムを総合サポート: http://groonga.org/ja/support/ パッチ採用 - プログラミングが楽しい人向けの採用プロセス: http://www.clear-code.com/recruitment/ コードリーダー育成支援 - 自然とリーダブルコードを書くチームへ: http://www.clear-code.com/services/code-reader/