Groongaで複数のトークナイザを使い分ける方法
はじめに
全文検索エンジン Groonga を使っていると、トークナイザによる検索結果の違いを比較したくなる時があります。
しかし、検索時に利用するインデックスを明示的に指定する方法は、現時点ではドキュメント化されていないようです。
執筆中です。
いろいろと試した結果、同じテーブルに対して複数のトークナイザによるインデックスを作成し、select時に使い分ける方法がわかったのでまとめておきます。なお、対象のバージョンは執筆時点で最新の 3.0.7 です。
利用するスキーマ
Blogテーブルの検索結果を、TokenBigramとTokenMecabの2種類のトークナイザで比較するケースを考えます。
検索対象のテーブル「Blog」
titleとbodyカラムを持ちます。
table_create --name Blog --flags TABLE_HASH_KEY \
--key_type ShortText
column_create --table Blog --name title --type ShortText
column_create --table Blog --name body --type ShortText
Bigramによる索引テーブル「BigramTerms」
Blogのtitleとbodyに対して、TokenBigramで索引blog_indexを作ります。
table_create --name BigramTerms \
--flags TABLE_PAT_KEY|KEY_NORMALIZE \
--key_type ShortText --default_tokenizer TokenBigram
column_create --table BigramTerms --name blog_index \
--flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION \
--type Blog --source title,body
Mecabによる索引テーブル「MecabTerms」
Blogのtitleとbodyに対して、TokenMecabで索引blog_indexを作ります。
table_create --name MecabTerms \
--flags TABLE_PAT_KEY|KEY_NORMALIZE \
--key_type ShortText --default_tokenizer TokenMecab
column_create --table MecabTerms --name blog_index \
--flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION \
--type Blog --source title,body
検索時にインデックスを指定する方法
以下のように--match_columnsにインデックス名を指定することで、インデックスを使い分けることができます。
BigramTermsで検索したい場合:
select --table Blog --match_columns BigramTerms.blog_index \
--query foo
MecabTermsで検索したい場合:
select --table Blog --match_columns MecabTerms.blog_index \
--query foo
なお、以下のようにカラム名だけを指定した場合は、どちらかのインデックスが使われるようですが、そのルールは不明です。
select --table Blog --match_columns 'title || body' --query foo
重み付けしたい場合
このようにしてインデックスを使い分けることができますが、カラムによって重み付けしたい場合があります。通常であれば、--match_columns 'title * 5 || body'のようにしてtitleを重視するといったことができますが、インデックスを明示したい場合はそうはいきません。
最初は --match_columns 'BigramTerms.blog_index.title * 5 || BigramTerms.blog_index.body' としたらできるかと思いましたが、これは --match_columns 'title * 5 || body' と同じ意味になりうまくいきません。
解決策としては、以下のようにカラムごとに別々のインデックスを作成します。
table_create --name BigramTerms \
--flags TABLE_PAT_KEY|KEY_NORMALIZE \
--key_type ShortText --default_tokenizer TokenBigram
column_create --table BigramTerms --name blog_title \
--flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION \
--type Blog --source title
column_create --table BigramTerms --name blog_body \
--flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION \
--type Blog --source body
そして、 --match_columns 'BigramTerms.blog_title * 5 || BigramTerms.blog_body' とすることで、インデックスを明示し、かつ重み付けした検索が可能になります。