Class: Groonga::IndexColumn

Inherits:
Column
  • Object
show all
Defined in:
ext/rb-grn-index-column.c,
ext/rb-grn-index-column.c

Overview

転置索引エントリを格納するカラム。このカラムを利用するこ とにより高速な全文検索を実現できる。

テーブルにGroonga::IndexColumnを定義する方法は Groonga::Table#define_index_columnを参照。

Instance Method Summary collapse

Methods inherited from Column

#clear_lock, #local_name, #lock, #locked?, #select, #table, #unlock

Instance Method Details

#[]=(id) ⇒ Object #[]=(id) ⇒ Object

IDがidであるレコードを高速に全文検索するため転置索引を作 成する。多くの場合、Groonga::Table#define_index_columnで :sourceオプションを指定することにより、自動的に全文検索 用の索引は更新されるので、明示的にこのメソッドを使うこと は少ない。

valueには文字列を指定する。

optionsを指定することにより、より索引の作成を制御できる。 optionsに指定可能な値は以下の通り。

:section

段落番号を指定する。省略した場合は1を指定したとみなされ る。

Groonga::Table#define_index_columnで {:with_section => true}を指定していなければい けない。

:old_value

以前の値を指定する。省略した場合は現在の値が用いられる。 通常は指定する必要はない。

:value

新しい値を指定する。valueを指定した場合とoptions{:value => value}を指定した場合は同じ動作とな る。

記事の段落毎に索引を作成する。

articles = Groonga::Array.create(:name => "<articles>")
articles.define_column("title", "ShortText")
articles.define_column("content", "Text")

terms = Groonga::Hash.create(:name => "<terms>",
                             :default_tokenizer => "TokenBigram")
content_index = terms.define_index_column("content", articles,
                                          :with_section => true)

content = <<-EOC
groonga は組み込み型の全文検索エンジンライブラリです。
DBMSやスクリプト言語処理系等に組み込むことによって、その
全文検索機能を強化することができます。また、リレーショナ
ルモデルに基づくデータストア機能を内包しており、groonga
単体でも高速なデータストアサーバとして使用することができ
ます。

■全文検索方式
転置索引型の全文検索エンジンです。転置索引は圧縮されてファ
イルに格納され、検索時のディスク読み出し量を小さく、かつ
局所的に抑えるように設計されています。用途に応じて以下の
索引タイプを選択できます。
EOC

groonga = articles.add(:title => "groonga", :content => content)

content.split(/\n{2,}/).each_with_index do |sentence, i|
  content_index[groonga] = {:value => sentence, :section => i + 1}
end

content_index.search("エンジン").collect do |record|
  p record.key["title"] # -> "groonga"
end


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
# File 'ext/rb-grn-index-column.c', line 166

static VALUE
rb_grn_index_column_array_set (VALUE self, VALUE rb_id, VALUE rb_value)
{
    grn_ctx *context = NULL;
    grn_obj *column, *range;
    grn_rc rc;
    grn_id id;
    unsigned int section;
    grn_obj *old_value, *new_value;
    VALUE original_rb_value, rb_section, rb_old_value, rb_new_value;

    original_rb_value = rb_value;

    rb_grn_index_column_deconstruct(SELF(self), &column, &context,
				    NULL, NULL,
				    &new_value, &old_value,
				    NULL, &range,
				    NULL, NULL);

    id = RVAL2GRNID(rb_id, context, range, self);

    if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_value, rb_cHash))) {
	VALUE hash_value;
	hash_value = rb_hash_new();
	rb_hash_aset(hash_value, RB_GRN_INTERN("value"), rb_value);
	rb_value = hash_value;
    }

    rb_grn_scan_options(rb_value,
			"section", &rb_section,
			"old_value", &rb_old_value,
			"value", &rb_new_value,
			NULL);

    if (NIL_P(rb_section))
	section = 1;
    else
	section = NUM2UINT(rb_section);

    if (NIL_P(rb_old_value)) {
	old_value = NULL;
    } else {
	GRN_BULK_REWIND(old_value);
	RVAL2GRNBULK(rb_old_value, context, old_value);
    }

    if (NIL_P(rb_new_value)) {
	new_value = NULL;
    } else {
	GRN_BULK_REWIND(new_value);
	RVAL2GRNBULK(rb_new_value, context, new_value);
    }

    rc = grn_column_index_update(context, column,
				 id, section, old_value, new_value);
    rb_grn_context_check(context, self);
    rb_grn_rc_check(rc, self);

    return original_rb_value;
}

#searchObject

call-seq:

column.search(query, options={}) -> Groonga::Hash

objectからqueryに対応するオブジェクトを検索し、見つかっ たオブジェクトのIDがキーになっているGroonga::Hashを返す。

利用可能なオプションは以下の通り。

:result

結果を格納するGroonga::Hash。指定しない場合は新しく Groonga::Hashを生成し、それに結果を格納して返す。

:operator

以下のどれかの値を指定する。nil, "or", "||", "and", "+", "&&", "but", "not", "-", "adjust", ">"。 それぞれ以下のようになる。(FIXME: 「以下」)

:exact

trueを指定すると完全一致で検索する

:longest_common_prefix

trueを指定するとqueryと同じ接頭辞をもつエントリのう ち、もっとも長いエントリを検索する

:suffix

trueを指定するとqueryが後方一致するエントリを検索す る

:prefix

trueを指定するとqueryが前方一致するレコードを検索す る

:near

trueを指定するとqueryに指定した複数の語が近傍に含ま れるレコードを検索する



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
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
# File 'ext/rb-grn-index-column.c', line 412

static VALUE
rb_grn_index_column_search (int argc, VALUE *argv, VALUE self)
{
    grn_ctx *context;
    grn_obj *column;
    grn_obj *range;
    grn_obj *query = NULL, *id_query = NULL, *string_query = NULL;
    grn_obj *result;
    grn_operator operator;
    grn_rc rc;
    VALUE rb_query, options, rb_result, rb_operator;

    rb_grn_index_column_deconstruct(SELF(self), &column, &context,
				    NULL, NULL,
				    NULL, NULL, NULL, &range,
				    &id_query, &string_query);

    rb_scan_args(argc, argv, "11", &rb_query, &options);

    if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cGrnQuery))) {
	grn_query *_query;
	_query = RVAL2GRNQUERY(rb_query);
	query = (grn_obj *)_query;
    } else if (CBOOL2RVAL(rb_obj_is_kind_of(rb_query, rb_cInteger))) {
	grn_id id;
	id = NUM2UINT(rb_query);
	GRN_TEXT_SET(context, id_query, &id, sizeof(grn_id));
	query = id_query;
    } else {
	const char *_query;
	_query = StringValuePtr(rb_query);
	GRN_TEXT_SET(context, string_query, _query, RSTRING_LEN(rb_query));
	query = string_query;
    }

    rb_grn_scan_options(options,
			"result", &rb_result,
			"operator", &rb_operator,
			NULL);

    if (NIL_P(rb_result)) {
	result = grn_table_create(context, NULL, 0, NULL,
				  GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
				  range, 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, column, query, result, operator, NULL);
    rb_grn_rc_check(rc, self);

    return rb_result;
}

#source=(Groonga) ⇒ Object

インデックス対象となるカラムを設定する。



367
368
369
370
371
372
373
374
# File 'ext/rb-grn-index-column.c', line 367

static VALUE
rb_grn_index_column_set_source (VALUE self, VALUE rb_source)
{
    if (!RVAL2CBOOL(rb_obj_is_kind_of(rb_source, rb_cArray)))
	rb_source = rb_ary_new3(1, rb_source);

    return rb_grn_index_column_set_sources(self, rb_source);
}

#sourcesGroonga::Columnの配列

インデックス対象となっているカラムの配列を返す。

Returns:



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'ext/rb-grn-index-column.c', line 233

static VALUE
rb_grn_index_column_get_sources (VALUE self)
{
    grn_ctx *context = NULL;
    grn_obj *column;
    grn_obj sources;
    grn_id *source_ids;
    VALUE rb_sources;
    int i, n;

    rb_grn_index_column_deconstruct(SELF(self), &column, &context,
				    NULL, NULL,
				    NULL, NULL, NULL, NULL,
				    NULL, NULL);

    GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL);
    grn_obj_get_info(context, column, GRN_INFO_SOURCE, &sources);
    rb_grn_context_check(context, self);

    n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id);
    source_ids = (grn_id *)GRN_BULK_HEAD(&sources);
    rb_sources = rb_ary_new2(n);
    for (i = 0; i < n; i++) {
	grn_obj *source;
	VALUE rb_source;

	source = grn_ctx_at(context, *source_ids);
	rb_source = GRNOBJECT2RVAL(Qnil, context, source, RB_GRN_FALSE);
	rb_ary_push(rb_sources, rb_source);
	source_ids++;
    }
    grn_obj_close(context, &sources);

    return rb_sources;
}

#sources=(Groonga) ⇒ Object

インデックス対象となる複数のカラムを配列で設定する。



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'ext/rb-grn-index-column.c', line 322

static VALUE
rb_grn_index_column_set_sources (VALUE self, VALUE rb_sources)
{
    VALUE exception;
    grn_ctx *context = NULL;
    grn_obj *column;
    int i, n;
    VALUE *rb_source_values;
    grn_id *sources;
    grn_rc rc;

    rb_grn_index_column_deconstruct(SELF(self), &column, &context,
				    NULL, NULL,
				    NULL, NULL, NULL, NULL,
				    NULL, NULL);

    n = RARRAY_LEN(rb_sources);
    rb_source_values = RARRAY_PTR(rb_sources);
    sources = ALLOCA_N(grn_id, n);
    for (i = 0; i < n; i++) {
	sources[i] = resolve_source_id(context, column, rb_source_values[i]);
    }

    {
	grn_obj bulk_sources;
	GRN_OBJ_INIT(&bulk_sources, GRN_BULK, 0, GRN_ID_NIL);
	GRN_TEXT_SET(context, &bulk_sources, sources, n * sizeof(grn_id));
	rc = grn_obj_set_info(context, column, GRN_INFO_SOURCE, &bulk_sources);
	exception = rb_grn_context_to_exception(context, self);
	grn_obj_close(context, &bulk_sources);
    }

    if (!NIL_P(exception))
	rb_exc_raise(exception);
    rb_grn_rc_check(rc, self);

    return Qnil;
}