Kouhei Sutou
kou****@clear*****
2009年 4月 21日 (火) 17:06:43 JST
須藤です。
groongaっぽいインデックスの使い方について教えて下さい。
# あまり理解できていなかったようです。。。
こんなテーブルを考えています。
<users>: GRN_OBJ_NO_KEY
カラム:
name: <shorttext>
<bookmarks>: GRN_OBJ_NO_KEY
カラム:
uri: <shorttext>
comment: <shorttext>
user: <users> # <users>テーブルを参照
user-vector: <index>|GRN_OBJ_COLUMN_VECTOR
# <bookmarks>.userと同じものをvectorでいれる
<index>: GRN_OBJ_HASH_KEY
カラム:
comment: <bookmarks>: GRN_COLUMN_INDEX # <bookmarks>.comment用インデックス
user: <bookmarks>: GRN_COLUMN_INDEX # <bookmarks>.user用インデックス
<index>.commentは特定のコメントを含むブックマーク一覧を取得
するためのものです。
<index>.userは特定のユーザのブックマーク一覧を取得するための
ものです。
# <index>.commentのGRN_INFO_SOURCEには<bookmarks>.commentを
# 指定していて、
# <index>.userのGRN_INFO_SOURCEには<bookmarks>.userを指定し
# ているとすると、
<index>.commentのように値(range)が<text>系のカラムのインデッ
クスの場合は、
grn_obj_set_value(): <bookmarks>.commentの値にGRN_BULKを設定
で、インデックスが作成され、
grn_obj_search(): <index>.commentからGRN_BULKにした検索ワー
ドで検索
で、インデックスを利用した検索ができると思います。
同じように、<index>.userのように値がテーブルオブジェクトのカ
ラムもインデックスの作成とインデックスを利用した検索をするの
がgroongaっぽいのかと思います。
以下のようにすると実現できているっぽいのですが、とても面倒な
ので、もっとうまい方法があるのではないかと思っています。
# GRN_INFO_SOURCEは利用できない?
インデックスの作成:
grn_obj_set_value():
- <bookmarks>.userの値にGRN_BULKで、<users>レコードのIDを設定
- <bookmarks>.user-vectorの値にGRN_VECTORで、<users>レコー
ドのIDを設定
- <index>.userの値にGRN_UVECTORで、<bookmarks>.user-vector
が<index>に追加したレコードのIDを設定
イメージコード: <bookmarks>.user
grn_obj *value;
grn_id user_id;
void *user_id_p;
user_id_p = &user_id;
value = grn_obj_open(context, GRN_BULK, 0, 0);
grn_bulk_write(context, value, user_id_p, sizeof(grn_id));
grn_obj_set_value(context, <bookmarks>.user,
bookmark_id, value, GRN_OBJ_SET);
イメージコード: <bookmarks>.user-vector
grn_obj *value;
grn_id user_id;
void *user_id_p;
user_id_p = &user_id;
value = grn_obj_open(context, GRN_VECTOR, 0, 0);
grn_vector_add_element(context, value, user_id_p, sizeof(grn_id),
0, 0);
grn_obj_set_value(context, <bookmarks>.user-vector,
bookmark_id, value, GRN_OBJ_SET);
イメージコード: <index>.user
grn_obj *value;
grn_id token_id;
void *token_id_p;
user_id_p = &user_id;
token_id = grn_table_lookup(context, <index>, user_id_p,
sizeof(grn_id), NULL);
token_id_p = &token_id;
value = grn_obj_open(context, GRN_UVECTOR, 0, 0);
grn_bulk_write(context, value, token_id_p, sizeof(grn_id));
grn_column_index_update(context, <index>.user,
bookmark_id, 1, NULL, value);
検索:
grn_obj_search(): <index>.userからGRN_BULKで<users>レコー
ドのIDを指定して検索(レコードIDが1なら"\001\000\000\000")
→見つかっているっぽい。
検索文字列がトークナイザーで壊されちゃいそうだけど大丈夫?
インデックスの更新が面倒なので、別の方法があるのではないかと
思っています。こういうときはhookを指定してうまい具合にやるも
のなのでしょうか?
もしよかったら、groongaらしいやりかたを教えてもらえないでしょ
うか?