Feature #1027

Feature #1014: ラッパーモード時にMATCH AGAINST条件で絞り込めるようにする

全文検索でヒットしたレコードのキー一覧をハンドラ内に格納する

Added by Masafumi oyamada about 7 years ago. Updated almost 7 years ago.

Status:完了Start date:06/29/2011
Priority:NormalDue date:
Assignee:Masafumi oyamada% Done:

100%

Category:-
Target version:0.9

Description

h2. 問題

現在は http://mroonga.github.com/userguide/wrapper.html#id6 にあるよう に、ラップ対象のストレージエンジンに対して全文検索部分を考慮しないクエ リが渡され、非効率的となっている。

これは、全文検索情報を返却する wrapper_ft_init_ext の結果が MySQL に渡 されてしまい、ハンドラ側で参照できなくなっていることに起因する。

ストレージエンジンインタフェースでは、全文検索時に wrapper_ft_init_ext というが呼ばれる。この関数は全文検索の対象となるカラム番号と全文検索に 用いられる文字列を MySQL から受け取り、その検索情報を格納したオブジェク トを返却するものである。返却されるオブジェクト (st_mrn_ft_info) には please という関数テーブルが格納されており、MySQL はこの関数テーブル内に 設定された「検索結果を取得する」関数を呼ぶ。このような設計となっている ため、検索を行うタイミングとしては、以下の 2 つが選択できる。

  1. wrapper_ft_init_ext 内で検索を行なってしまい st_mrn_ft_info->please->* ではその検索結果(st_mrn_ft_info 内で保持 される)を返すだけにする。
  2. wrapper_ft_init_ext 内では検索に必要な情報の設定だけを行い st_mrn_ft_info->please->* の関数が呼ばれた際に実際の検索を行う。

現在の実装では 1. の wrapper_ft_init_ext 内で検索を行なってしまう方式を 採用している。

ここで注意点としては、一つのクエリ内に MATCH AGAINST が複数あった場合、 その回数だけ wrapper_ft_init_ext が呼ばれる、というものがあげられる。そ のため groonga ストレージエンジンは wrapper_ft_init_ext によりヒットし たレコードのキー一覧を検索結果テーブルに格納する際、結果のマージ (AND か OR) を行うことが期待される。

h2. 期待する状態

ハンドラ内に検索結果のテーブルが設けられており、cond_push などの関数か ら、現在のクエリに対する全文検索でヒットしたレコードのキー一覧を取得す ることができるようになっている。

h2. 解決方法

ハンドラ内に検索結果テーブルを設け、wrapper_ft_init_ext 内で全文検索に よりヒットしたレコードのキー一覧を、そのテーブルに設定するようにする。

テーブルは一つのクエリが実行される度に生成し、クエリの実行が終了する際 に削除する。

h2. Appendix

h3. cond_push

cond_push 内では InnoDB などのラップ対象となるストレージエンジンに投げ るクエリを構成する。この際に全文検索の結果レコードだけを対象とするため、 ヒットしたレコード一覧のキーをこの中から取得できるようにするのが、今回 の目的。

const COND *ha_mroonga::cond_push(const COND *cond)
{
  MRN_DBUG_ENTER_METHOD();
  if (share->wrapper_mode)
    DBUG_RETURN(wrapper_cond_push(cond));
  DBUG_RETURN(default_cond_push(cond));
}

h3. 全文検索情報

ha_mroonga.h で定義されている。

struct st_mrn_ft_info
{
  struct _ft_vft *please;
  grn_ctx *ctx;
  grn_obj *table;
  grn_obj *result;
  grn_obj *score_column;
  grn_obj key;
  grn_obj score;
  KEY *primary_key_info;
  uint primary_key_length;
  grn_id record_id; // TODO: remove me.
};

h3. 関数テーブル

ha_mroonga.cc で定義されている。

static _ft_vft mrn_wrapper_ft_vft = {
  mrn_wrapper_ft_read_next,
  mrn_wrapper_ft_find_relevance,
  mrn_wrapper_ft_close_search,
  mrn_wrapper_ft_get_relevance,
  mrn_wrapper_ft_reinit_search
};

h3. MySQL のプライマリキー

MySQL では、プライマリキーが内部的には文字列(バイト列)として管理され る(バイト列を渡すと実際のキーが取得できる)。

この操作には key_copy という関数を使う。record には値、それ以降にキーの 情報を指定すると、第一引数で指定した領域にキーの値がコピーされる。

key_copy((uchar *)(GRN_TEXT_VALUE(&(info->key))), record,
         info->primary_key_info, info->primary_key_length);

Subtasks

Feature #1028: ハンドラにテーブルを持たせる完了Kouhei Sutou

History

#1 Updated by Masafumi oyamada about 7 years ago

まずは MATCH AGAINST が一つしか無い場合を対象とする。

#2 Updated by Kouhei Sutou almost 7 years ago

  • Target version changed from groonga-storage-engine 0.8 to 0.9

#3 Updated by Kouhei Sutou almost 7 years ago

  • Status changed from 担当者作業中 to 完了チェック待ち

ここらへんはSQLレイヤーがうまくやってくれていそうなので、一旦closeとする。

#4 Updated by Kouhei Sutou almost 7 years ago

  • Status changed from 完了チェック待ち to 完了

Also available in: Atom PDF