[groonga-dev,02612] Re: [mroonga] asterisk wildcard operator

Back to archive index

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/




groonga-dev メーリングリストの案内
Back to archive index