4.7. match_columnsパラメータ¶
4.7.1. 複数のカラムに対する全文検索¶
Groongaでは、複数のカラムを対象とした全文検索を行うことができます。例えば、ブログのテーブルで、タイトルと内容とがそれぞれ別のカラムに入ったものがあるとしましょう。「タイトルもしくは内容に特定の単語を含む」検索を行いたいとします。
この場合、2つのインデックス作成方式があります。1つは、それぞれのカラムに1つずつインデックスを付与する方式です。もう1つは、複数のカラムに対して1つのインデックスを付与する方式です。Groongaでは、どちらの形式のインデックスが存在している場合でも、同一の記法で全文検索を行うことができます。
4.7.1.1. カラムごとにインデックスを付与する場合¶
カラムごとにインデックスを作成する方法はこの通りです。
まず、 Blog1
テーブルを作成し、 title
カラムと message
カラムを追加します。 title
カラムにブログのタイトルを保存し、 message
カラムにブログの本文を保存します。
インデックス用の IndexBlog1
テーブルも作り、 title
カラムのインデックス用に index_title
カラム、 message
カラムのインデックス用に index_message
カラムと、それぞれ1カラムごとに1つずつ追加しています。
実行例:
table_create --name Blog1 --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog1 --name title --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog1 --name message --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name IndexBlog1 --flags TABLE_PAT_KEY --key_type ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog1 --name index_title --flags COLUMN_INDEX|WITH_POSITION --type Blog1 --source title
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog1 --name index_message --flags COLUMN_INDEX|WITH_POSITION --type Blog1 --source message
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Blog1
[
{"_key":"grn1","title":"Groonga test","message":"Groonga message"},
{"_key":"grn2","title":"baseball result","message":"rakutan eggs 4 - 4 Groonga moritars"},
{"_key":"grn3","title":"Groonga message","message":"none"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
match_columns
オプションで、検索対象のカラムを複数指定することが出来ます。検索する文字列は query
オプションで指定します。これを使うことで、タイトルと本文を全文検索することができます。
実際にブログエントリを検索してみましょう。
実行例:
select --table Blog1 --match_columns title||message --query groonga
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 3
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 1,
# "grn1",
# "Groonga message",
# "Groonga test"
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ],
# [
# 2,
# "grn2",
# "rakutan eggs 4 - 4 Groonga moritars",
# "baseball result"
# ]
# ]
# ]
# ]
select --table Blog1 --match_columns title||message --query message
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 2
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ],
# [
# 1,
# "grn1",
# "Groonga message",
# "Groonga test"
# ]
# ]
# ]
# ]
select --table Blog1 --match_columns title --query message
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 1
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ]
# ]
# ]
# ]
4.7.1.2. 複数のカラムにまたがったインデックスを付与する場合¶
Groongaでは複数のカラムにまたがったインデックスもサポートしています。
インデックスカラムが1つしかないというのが違いです。 title
と message
の2つのカラムに対するインデックスが共通になっています。
共通のインデックスを用いても、 title
カラムのみでの検索、 message
カラムのみでの検索、 title
もしくは message
カラムでの検索、全ての検索を行うことができます。
実行例:
table_create --name Blog2 --flags TABLE_HASH_KEY --key_type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog2 --name title --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table Blog2 --name message --flags COLUMN_SCALAR --type ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
table_create --name IndexBlog2 --flags TABLE_PAT_KEY --key_type ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create --table IndexBlog2 --name index_blog --flags COLUMN_INDEX|WITH_POSITION|WITH_SECTION --type Blog2 --source title,message
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Blog2
[
{"_key":"grn1","title":"Groonga test","message":"Groonga message"},
{"_key":"grn2","title":"baseball result","message":"rakutan eggs 4 - 4 Groonga moritars"},
{"_key":"grn3","title":"Groonga message","message":"none"}
]
# [[0, 1337566253.89858, 0.000355720520019531], 3]
実際に前と同じ例で検索してみましょう。結果は上の例と同じになります。
実行例:
select --table Blog2 --match_columns title||message --query groonga
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 3
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 1,
# "grn1",
# "Groonga message",
# "Groonga test"
# ],
# [
# 2,
# "grn2",
# "rakutan eggs 4 - 4 Groonga moritars",
# "baseball result"
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ]
# ]
# ]
# ]
select --table Blog2 --match_columns title||message --query message
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 2
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 1,
# "grn1",
# "Groonga message",
# "Groonga test"
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ]
# ]
# ]
# ]
select --table Blog2 --match_columns title --query message
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 1
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_key",
# "ShortText"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 3,
# "grn3",
# "none",
# "Groonga message"
# ]
# ]
# ]
# ]
注釈
"インデックスはどちらがよい方法なのか"と疑問に思うかもしれません。それは場合によります。
カラムごとのインデックス - マルチカラムインデックスよりも更新性能が良い傾向があります。一方、ディスク使用効率はあまり良くありません。
マルチカラムインデックス - バッファを共有するためディスク使用効率が良いです。一方、更新性能があまり良くありません。
4.7.2. インデックス名を指定した全文検索¶
Groongaは、インデックス名を指定した全文検索もサポートしています。
このセクションでは、インデックス名を指定した全文検索の方法を学びます。
インデックス名の指定について具体的な例を示します。
実行例:
table_create Entries TABLE_HASH_KEY ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries title COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Entries body COLUMN_SCALAR ShortText
# [[0, 1337566253.89858, 0.000355720520019531], true]
load --table Entries
[
{"_key": "http://example.com/entry1", "title":"Hello Groonga.", "body":"This is my first entry."},
{"_key": "http://example.com/entry2", "title":"Hello world.", "body":"I love Groonga!"},
{"_key": "http://example.com/entry3", "title":"Hello Mroonga, bye Groonga.", "body":"I use Mroonga."},
{"_key": "http://example.com/entry4", "title":"Say, Hello Groonga!", "body":"I'm back."}
]
# [[0, 1337566253.89858, 0.000355720520019531], 4]
table_create Terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_title COLUMN_INDEX|WITH_POSITION Entries title
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_body COLUMN_INDEX|WITH_POSITION Entries body
# [[0, 1337566253.89858, 0.000355720520019531], true]
column_create Terms entries_whole COLUMN_INDEX|WITH_POSITION|WITH_SECTION Entries title,body
# [[0, 1337566253.89858, 0.000355720520019531], true]
title
と body
カラムを持つテーブルがあります。また、語彙表は title
と body
のカラムのインデックスを持っています。
語彙表には、3つのインデックスカラムがあります。
entries_title:
title
のインデックスカラムentries_body:
body
のインデックスカラムentries_whole:
title
とbody
のインデックスカラム
特定のデータカラムと結びついたインデックスカラムを指定した場合は、暗黙的にそのデータカラムだけを検索します。
例えば、 title
または body
だけを検索したい場合は、 Terms.entries_title
または Terms.entries_body
をインデックスカラムに指定します。
実行例:
select --table Entries --output_columns title --match_columns Terms.entries_title --query "Groonga"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 3
# ],
# [
# [
# "title",
# "ShortText"
# ]
# ],
# [
# "Hello Groonga."
# ],
# [
# "Hello Mroonga, bye Groonga."
# ],
# [
# "Say, Hello Groonga!"
# ]
# ]
# ]
# ]
この例では、Terms.entries_title
をインデックスとして title
カラムを対象に"Groonga"を検索します。
実行例:
select --table Entries --output_columns body --match_columns Terms.entries_body --query "Groonga"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 1
# ],
# [
# [
# "body",
# "ShortText"
# ]
# ],
# [
# "I love Groonga!"
# ]
# ]
# ]
# ]
この例では、 Terms.entries_whole
をインデックスとして、 body
カラムを対象に"Groonga"を検索します。
複数カラムにまたがるインデックスは、インデックスカラムの後にデータカラム名を指定することができます。これは、どのインデックスを使ってどのデータカラムを検索するかを明示しています。
例えば、 entries_whole
インデックスが付いた title
または body
を検索する場合、 Terms.entries_whole.title
または Terms.entries_whole.body
を指定します。 Terms.entries_whole
をインデックスとして使い、 title
カラムまたは、 body
カラムを対象に検索します。
実行例:
select --table Entries --output_columns title --match_columns Terms.entries_whole.title --query "Groonga"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 3
# ],
# [
# [
# "title",
# "ShortText"
# ]
# ],
# [
# "Hello Groonga."
# ],
# [
# "Hello Mroonga, bye Groonga."
# ],
# [
# "Say, Hello Groonga!"
# ]
# ]
# ]
# ]
この例では、 Terms.entries_whole
をインデックスとして、 title
カラムを対象に"Groonga"を検索します。
実行例:
select --table Entries --output_columns body --match_columns Terms.entries_whole.body --query "Groonga"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 1
# ],
# [
# [
# "body",
# "ShortText"
# ]
# ],
# [
# "I love Groonga!"
# ]
# ]
# ]
# ]
この例では、 Terms.entries_whole
をインデックスとして、 body
カラムを対象に"Groonga"を検索します。
4.7.4. インデックスの重み¶
もし、インデックスカラムがデータカラムに対して作成されていたら、インデックスの重みを使って検索できます。例えば、 Groonga
が重要なキーワードとしてブログエントリに含まれている Blog1
テーブルをインデックスの重みを使って検索してみましょう。一般的に重要なキーワードはブログのタイトルに含まれます。そのため、 title
カラムが Groonga
を含んでいればそのスコア( _score
)が message
カラムにくらべて高くないといけません。インデックスの重みはそのような目的に使われます。
次は、tittle
や message
カラムに重要なキーワードとして Groonga
が含まれているブログエントリを検索する例です。
サンプルのスキーマとデータは カラムごとにインデックスを付与する場合 と同じです。
実行例:
select --table Blog1 --match_columns 'IndexBlog1.index_title * 10 || IndexBlog1.index_message' --query 'Groonga' --output_columns "_id, _score, *"
# [
# [
# 0,
# 1337566253.89858,
# 0.000355720520019531
# ],
# [
# [
# [
# 3
# ],
# [
# [
# "_id",
# "UInt32"
# ],
# [
# "_score",
# "Int32"
# ],
# [
# "message",
# "ShortText"
# ],
# [
# "title",
# "ShortText"
# ]
# ],
# [
# 1,
# 11,
# "Groonga message",
# "Groonga test"
# ],
# [
# 3,
# 10,
# "none",
# "Groonga message"
# ],
# [
# 2,
# 1,
# "rakutan eggs 4 - 4 Groonga moritars",
# "baseball result"
# ]
# ]
# ]
# ]
上記の例では、 'IndexBlog1.index_title * 10 || IndexBlog1.index_message'
が --match_columns
に指定されています。これは title
カラム( IndexBlog1.index_title
インデックスを使って検索)が Groonga
にマッチしたら、その重みは10倍されます。もし message
カラム( IndexBlog1.index_message
インデックスを使って検索)が Groonga
にマッチしたら、その重みは1(既定値)になります。もし Groonga
が title
と message
カラムの両方にマッチしたら、その重みはこの場合11(10 + 1)になります。
結果として、 Groonga test
ブログエントリがリストの最初に表示されます。