Class: Groonga::PatriciaTrie
- Includes:
- GrnTableKeySupport
- Defined in:
- ext/rb-grn-patricia-trie.c,
lib/groonga/patricia-trie.rb,
ext/rb-grn-patricia-trie.c
Overview
各レコードをパトリシアトライで管理するテーブル。ハッシュ テーブルに比べて完全一致検索の速度がやや遅いが、前方一致 検索・共通接頭辞探索などの検索ができる。またカーソルを用 いてキーの昇降順にレコードを取り出すことができる。
Class Method Summary collapse
-
.create ⇒ Object
各レコードをパトリシアトライで管理するテーブルを生成する。 ブロックを指定すると、そのブロックに生成したテーブルが渡さ れ、ブロックを抜けると自動的にテーブルが破棄される。.
Instance Method Summary collapse
-
#prefix_search(prefix) ⇒ Groonga::Hash
キーがprefixに前方一致するレコードのIDがキーに入っている Groonga::Hashを返す。マッチするレコードがない場合は空の Groonga::Hashが返る。.
-
#scan ⇒ Object
stringを走査し、patricia_trie内に格納されているキーに マッチした部分文字列の情報をブロックに渡す。複数のキーが マッチする場合は最長一致するキーを優先する。.
-
#search(key, options = nil) ⇒ Groonga::Hash
keyにマッチするレコードのIDがキーに入っている Groonga::Hashを返す。マッチするレコードがない場合は空の Groonga::Hashが返る。.
-
#tag_keys(text) ⇒ Object
call-seq: patricia_trie.tag_keys(text) {|record, word| …} -> String.
Methods inherited from Table
#[], #add_column, #clear_lock, #column, #column_value, #columns, #define_column, #define_index_column, #delete, #difference!, #each, #group, #initialize, #inspect, #intersection!, #lock, #locked?, #merge!, open, #open_cursor, #records, #select, #set_column_value, #set_value, #size, #sort, #truncate, #union!, #unlock, #value
Constructor Details
This class inherits a constructor from Groonga::Table
Class Method Details
.Groonga::PatriciaTrie.create(options = {}) ⇒ Groonga::PatriciaTrie .Groonga::PatriciaTrie.create(options = ) { ... } ⇒ Object
各レコードをパトリシアトライで管理するテーブルを生成する。 ブロックを指定すると、そのブロックに生成したテーブルが渡さ れ、ブロックを抜けると自動的にテーブルが破棄される。
optionsに指定可能な値は以下の通り。
:context
-
テーブルが利用するGroonga::Context。省略すると Groonga::Context.defaultを用いる。
:name
-
テーブルの名前。名前をつけると、Groonga::Context#[]に名 前を指定してテーブルを取得することができる。省略すると 無名テーブルになり、テーブルIDでのみ取得できる。
:path
-
テーブルを保存するパス。パスを指定すると永続テーブルとな り、プロセス終了後もレコードは保持される。次回起動時に Groonga::PatriciaTrie.openで保存されたレコードを利用する ことができる。省略すると一時テーブルになり、プロセスが終 了するとレコードは破棄される。
:persistent
-
true
を指定すると永続テーブルとなる。path
を省略した 場合は自動的にパスが付加される。:context
で指定した Groonga::Contextに結びついているデータベースが一時デー タベースの場合は例外が発生する。 :key_normalize
-
true
を指定するとキーを正規化する。 :key_with_sis
-
true
を指定するとキーの文字列の全suffixが自動的に登 録される。 :key_type
-
キーの種類を示すオブジェクトを指定する。キーの種類には型 名(“Int32”や“ShortText”など)またはGroonga::Typeまたは テーブル(Groonga::Array、Groonga::Hash、 Groonga::PatriciaTrieのどれか)を指定する。
Groonga::Typeを指定した場合は、その型が示す範囲の値をキー として使用する。ただし、キーの最大サイズは4096バイトで あるため、Groonga::Type::TEXTやGroonga::Type::LONG_TEXT は使用できない。
テーブルを指定した場合はレコードIDをキーとして使用する。 指定したテーブルのGroonga::Recordをキーとして使用するこ ともでき、その場合は自動的にGroonga::Recordからレコード IDを取得する。
省略した場合は文字列をキーとして使用する。この場合、 4096バイトまで使用可能である。
:value_type
-
値の型を指定する。省略すると値のための領域を確保しない。 値を保存したい場合は必ず指定すること。
参考: Groonga::Type.new
:default_tokenizer
-
Groonga::IndexColumnで使用するトークナイザを指定する。 デフォルトでは何も設定されていないので、テーブルに Groonga::IndexColumnを定義する場合は
"TokenBigram"
などを指定する必要がある。 :sub_records
-
true
を指定すると#groupでグループ化したときに、 Groonga::Record#n_sub_recordsでグループに含まれるレコー ドの件数を取得できる。
使用例:
無名一時テーブルを生成する。
Groonga::PatriciaTrie.create
無名永続テーブルを生成する。
Groonga::PatriciaTrie.create(:path => "/tmp/hash.grn")
名前付き永続テーブルを生成する。ただし、ファイル名は気に しない。
Groonga::PatriciaTrie.create(:name => "Bookmarks",
:persistent => true)
それぞれのレコードに512バイトの値を格納できる無名一時テー ブルを生成する。
Groonga::PatriciaTrie.create(:value => 512)
キーとして文字列を使用する無名一時テーブルを生成する。
Groonga::PatriciaTrie.create(:key_type => Groonga::Type::SHORT_TEXT)
キーとして文字列を使用する無名一時テーブルを生成する。 (キーの種類を表すオブジェクトは文字列で指定。)
Groonga::PatriciaTrie.create(:key_type => "ShortText")
キーとしてBookmarks
テーブルのレコードを使用す る無名一時テーブルを生成する。
bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks")
Groonga::PatriciaTrie.create(:key_type => bookmarks)
キーとしてBookmarks
テーブルのレコードを使用す る無名一時テーブルを生成する。 (テーブルは文字列で指定。)
Groonga::PatriciaTrie.create(:name => "Bookmarks")
Groonga::PatriciaTrie.create(:key_type => "Bookmarks")
全文検索用のトークンをバイグラムで切り出す無名一時テーブ ルを生成する。
bookmarks = Groonga::PatriciaTrie.create(:name => "Bookmarks")
bookmarks.define_column("comment", "Text")
terms = Groonga::PatriciaTrie.create(:name => "Terms",
:default_tokenizer => "TokenBigram")
terms.define_index_column("content", bookmarks,
:source => "Bookmarks.comment")
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'ext/rb-grn-patricia-trie.c', line 155
static VALUE
rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
{
grn_ctx *context;
grn_obj *key_type = NULL, *value_type = NULL, *table;
const char *name = NULL, *path = NULL;
unsigned name_size = 0;
grn_obj_flags flags = GRN_TABLE_PAT_KEY;
VALUE rb_table;
VALUE options, rb_context, rb_name, rb_path, rb_persistent;
VALUE rb_key_normalize, rb_key_with_sis, rb_key_type;
VALUE rb_value_type;
VALUE rb_default_tokenizer, rb_sub_records;
rb_scan_args(argc, argv, "01", &options);
rb_grn_scan_options(options,
"context", &rb_context,
"name", &rb_name,
"path", &rb_path,
"persistent", &rb_persistent,
"key_normalize", &rb_key_normalize,
"key_with_sis", &rb_key_with_sis,
"key_type", &rb_key_type,
"value_type", &rb_value_type,
"default_tokenizer", &rb_default_tokenizer,
"sub_records", &rb_sub_records,
NULL);
context = rb_grn_context_ensure(&rb_context);
if (!NIL_P(rb_name)) {
name = StringValuePtr(rb_name);
name_size = RSTRING_LEN(rb_name);
flags |= GRN_OBJ_PERSISTENT;
}
if (!NIL_P(rb_path)) {
path = StringValueCStr(rb_path);
flags |= GRN_OBJ_PERSISTENT;
}
if (RVAL2CBOOL(rb_persistent))
flags |= GRN_OBJ_PERSISTENT;
if (RVAL2CBOOL(rb_key_normalize))
flags |= GRN_OBJ_KEY_NORMALIZE;
if (RVAL2CBOOL(rb_key_with_sis))
flags |= GRN_OBJ_KEY_WITH_SIS;
if (NIL_P(rb_key_type)) {
flags |= GRN_OBJ_KEY_VAR_SIZE;
} else {
key_type = RVAL2GRNOBJECT(rb_key_type, &context);
}
if (!NIL_P(rb_value_type))
value_type = RVAL2GRNOBJECT(rb_value_type, &context);
if (RVAL2CBOOL(rb_sub_records))
flags |= GRN_OBJ_WITH_SUBREC;
table = grn_table_create(context, name, name_size, path,
flags, key_type, value_type);
if (!table)
rb_grn_context_check(context, rb_ary_new4(argc, argv));
rb_table = GRNOBJECT2RVAL(klass, context, table, RB_GRN_TRUE);
if (!NIL_P(rb_default_tokenizer))
rb_funcall(rb_table, rb_intern("default_tokenizer="), 1,
rb_default_tokenizer);
if (rb_block_given_p())
return rb_ensure(rb_yield, rb_table, rb_grn_object_close, rb_table);
else
return rb_table;
}
|
Instance Method Details
#prefix_search(prefix) ⇒ Groonga::Hash
キーがprefixに前方一致するレコードのIDがキーに入っている Groonga::Hashを返す。マッチするレコードがない場合は空の Groonga::Hashが返る。
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
# File 'ext/rb-grn-patricia-trie.c', line 443
static VALUE
rb_grn_patricia_trie_prefix_search (VALUE self, VALUE rb_prefix)
{
grn_ctx *context;
grn_obj *table, *key, *domain, *result;
grn_id domain_id;
VALUE rb_result;
rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
&key, &domain_id, &domain,
NULL, NULL, NULL,
NULL);
result = grn_table_create(context, NULL, 0, NULL,
GRN_OBJ_TABLE_HASH_KEY,
table, 0);
rb_grn_context_check(context, self);
rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
GRN_BULK_REWIND(key);
RVAL2GRNKEY(rb_prefix, context, key, domain_id, domain, self);
grn_pat_prefix_search(context, (grn_pat *)table,
GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key),
(grn_hash *)result);
rb_grn_context_check(context, self);
return rb_result;
}
|
#scan(string) ⇒ Array #scan(string) {|record, word, start, length| ... } ⇒ Object
stringを走査し、patricia_trie内に格納されているキーに マッチした部分文字列の情報をブロックに渡す。複数のキーが マッチする場合は最長一致するキーを優先する。
- record
-
マッチしたキーのGroonga::Record。
- word
-
マッチした部分文字列。
- start
-
string内でのwordの出現位置。(バイト単位)
- length
-
wordの長さ。(バイト探知)
ブロックを指定しない場合は、マッチした部分文字列の情報を まとめて配列として返す。
words = Groonga::PatriciaTrie.create(:key_type => "ShortText",
:key_normalize => true)
words.add("リンク")
adventure_of_link = words.add('リンクの冒険')
words.add('冒険')
gaxtu = words.add('ガッ')
muteki = words.add('MUTEKI')
text = 'muTEki リンクの冒険 ミリバール ガッ'
words.scan(text).each do |record, word, start, length|
p [record.key, word, start, length]
# -> ["MUTEKI", "muTEki", 0, 6]
# -> ["リンクの冒険", "リンクの冒険", 7, 18]
# -> ["ガッ", "ガッ", 42, 6]
end
words.scan(text)
# -> [[muteki, "muTEki", 0, 6],
# [adventure_of_link, "リンクの冒険", 7, 18],
# [gaxtu, "ガッ", 42, 6]]
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
# File 'ext/rb-grn-patricia-trie.c', line 373
static VALUE
rb_grn_patricia_trie_scan (VALUE self, VALUE rb_string)
{
grn_ctx *context;
grn_obj *table;
VALUE rb_result = Qnil;
grn_pat_scan_hit hits[1024];
const char *string;
long string_length;
rb_grn_boolean block_given;
string = StringValuePtr(rb_string);
string_length = RSTRING_LEN(rb_string);
rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL);
block_given = rb_block_given_p();
if (!block_given)
rb_result = rb_ary_new();
while (string_length > 0) {
const char *rest;
int i, n_hits;
long previous_offset = 0;
n_hits = grn_pat_scan(context, (grn_pat *)table,
string, string_length,
hits, sizeof(hits) / sizeof(*hits),
&rest);
for (i = 0; i < n_hits; i++) {
VALUE record, term, matched_info;
if (hits[i].offset < previous_offset)
continue;
record = rb_grn_record_new(self, hits[i].id, Qnil);
term = rb_grn_context_rb_string_new(context,
string + hits[i].offset,
hits[i].length);
matched_info = rb_ary_new3(4,
record,
term,
UINT2NUM(hits[i].offset),
UINT2NUM(hits[i].length));
if (block_given) {
rb_yield(matched_info);
} else {
rb_ary_push(rb_result, matched_info);
}
previous_offset = hits[i].offset;
}
string_length -= rest - string;
string = rest;
}
return rb_result;
}
|
#search(key, options = nil) ⇒ Groonga::Hash
keyにマッチするレコードのIDがキーに入っている Groonga::Hashを返す。マッチするレコードがない場合は空の Groonga::Hashが返る。
optionsで:result
を指定することにより、そのテーブルにマッ チしたレコードIDがキーのレコードを追加することができる。 :result
にテーブルを指定した場合は、そのテーブルが返る。
optionsに指定可能な値は以下の通り。
:result
-
結果を格納するテーブル。
:operator
-
マッチしたレコードをどのように扱うか。指定可能な値は以 下の通り。省略した場合はGroonga::Operation::OR。
- Groonga::Operation::OR
-
マッチしたレコードを追加。すでにレコードが追加され ている場合は何もしない。
- Groonga::Operation::AND
-
マッチしたレコードのスコアを増加。マッチしなかった レコードを削除。
- Groonga::Operation::BUT
-
マッチしたレコードを削除。
- Groonga::Operation::ADJUST
-
マッチしたレコードのスコアを増加。
:type
-
?????
複数のキーで検索し、結果を1つのテーブルに集める。
result = nil
keys = ["morita", "gunyara-kun", "yu"]
keys.each do |key|
result = users.search(key, :result => result)
end
result.each do |record|
user = record.key
p user.key # -> "morita"または"gunyara-kun"または"yu"
end
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'ext/rb-grn-patricia-trie.c', line 280
static VALUE
rb_grn_patricia_trie_search (int argc, VALUE *argv, VALUE self)
{
grn_rc rc;
grn_ctx *context;
grn_obj *table;
grn_id domain_id;
grn_obj *key, *domain, *result;
grn_operator operator;
grn_search_optarg search_options;
rb_grn_boolean search_options_is_set = RB_GRN_FALSE;
VALUE rb_key, options, rb_result, rb_operator, rb_type;
rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
&key, &domain_id, &domain,
NULL, NULL, NULL,
NULL);
rb_scan_args(argc, argv, "11", &rb_key, &options);
RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self);
rb_grn_scan_options(options,
"result", &rb_result,
"operator", &rb_operator,
"type", &rb_type,
NULL);
if (NIL_P(rb_result)) {
result = grn_table_create(context, NULL, 0, NULL,
GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
table, 0);
rb_grn_context_check(context, self);
rb_result = GRNOBJECT2RVAL(Qnil, context, result, RB_GRN_TRUE);
} else {
result = RVAL2GRNOBJECT(rb_result, &context);
}
operator = RVAL2GRNOPERATOR(rb_operator);
rc = grn_obj_search(context, table, key,
result, operator,
search_options_is_set ? &search_options : NULL);
rb_grn_rc_check(rc, self);
return rb_result;
}
|
#tag_keys(text) ⇒ Object
call-seq:
patricia_trie.tag_keys(text) {|record, word| ...} -> String
textを走査し、レコードのキーとマッチする部分文字列ごとに そのレコードがrecordとして、その部分文字列がwordとして、 ブロックが呼び出される。ブロックから返された文字列が元の部 分文字列と置換される。全てのヒットに対してのその置換処理が 行われた文字列が返される。
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/groonga/patricia-trie.rb', line 28 def tag_keys(text) position = 0 result = '' if text.respond_to?(:encoding) encoding = text.encoding bytes = text.dup.force_encoding("ascii-8bit") else encoding = nil bytes = text end scan(text) do |record, word, start, length| previous_text = bytes[position...start] previous_text.force_encoding(encoding) if encoding result << previous_text result << yield(record, word) position = start + length end last_text = bytes[position..-1] unless last_text.empty? last_text.force_encoding(encoding) if encoding result << last_text end result end |