groongaでは、 select コマンドにquery_expansionパラメータを指定することによって、ユーザが指定した検索文字列を適宜拡張することが可能です。
たとえば、ユーザが'シークヮーサー'という文字列で検索した場合に、'シークヮーサー OR シークァーサー'で検索した場合と同一の結果を返すことによって、本来ユーザが必要とする結果をよりもれなく検索できるようになります。
クエリ拡張機能を使用するためには、検索対象となる文書を格納するテーブル(ここでは文書テーブルと呼びます)以外に、ユーザの指定した検索文字列を置換するためのテーブル(ここでは置換テーブルと呼びます)を準備します。置換テーブルでは、その主キーが置換前の文字列となり、文字列型(ShortText)のカラムの値が置換後の文字列となります。
TODO: 文字列型のベクターカラムでも可能であり、その場合は各要素をORでつなげたものに置換されるということを記述する。
実際に文書テーブルと置換テーブルを作成してみましょう。
Execution example:
> table_create Doc TABLE_PAT_KEY ShortText
[[0,1335519662.68773,0.000400543212890625],true]
> column_create Doc body COLUMN_SCALAR ShortText
[[0,1335519662.88919,0.000899314880371094],true]
> table_create Term TABLE_PAT_KEY|KEY_NORMALIZE ShortText --default_tokenizer TokenBigram
[[0,1335519663.09089,0.000370979309082031],true]
> column_create Term Doc_body COLUMN_INDEX|WITH_POSITION Doc body
[[0,1335519663.29217,0.00676441192626953],true]
> table_create Synonym TABLE_PAT_KEY ShortText
[[0,1335519663.4998,0.000351667404174805],true]
> column_create Synonym body COLUMN_SCALAR ShortText
[[0,1335519663.70094,0.000846624374389648],true]
> load --table Doc
> [
> {"_key": "001", "body": "すっぱいブドウと甘いシークァーサー"},
> {"_key": "002", "body": "シークヮーサージュースとゴーヤチャンプル"},
> ]
[[0,1335519663.90262,0.801640033721924],2]
> load --table Synonym
> [
> {"_key": "シークァーサー", "body": "(シークァーサー OR シークヮーサー)"},
> {"_key": "シークヮーサー", "body": "(シークァーサー OR シークヮーサー)"},
> ]
[[0,1335519664.905,0.801484823226929],2]
この例では、ユーザが"シークァーサー"と入力しても、"シークヮーサー"と入力しても、それぞれの異なる表記の文書をもれなく検索するための置換テーブルを作成しています。
それでは実際に、準備した置換テーブルを使ってみましょう。まずは、query_expansionパラメータを指定せずにselectコマンドを使って検索してみます。
Execution example:
> select Doc --match_columns body --query "シークァーサー"
[
[
0,
1335519665.90753,
0.000537633895874023
],
[
[
[
1
],
[
[
"_id",
"UInt32"
],
[
"_key",
"ShortText"
],
[
"body",
"ShortText"
]
],
[
1,
"001",
"すっぱいブドウと甘いシークァーサー"
]
]
]
]
> select Doc --match_columns body --query "シークヮーサー"
[
[
0,
1335519666.10912,
0.000688791275024414
],
[
[
[
1
],
[
[
"_id",
"UInt32"
],
[
"_key",
"ShortText"
],
[
"body",
"ShortText"
]
],
[
2,
"002",
"シークヮーサージュースとゴーヤチャンプル"
]
]
]
]
指定された文字列に完全に一致するレコードのみがそれぞれヒットします。次に、query_expansionパラメータに、準備したSynonymテーブルのbodyカラムを指定してみましょう。
Execution example:
> select Doc --match_columns body --query "シークァーサー" --query_expansion Synonym.body
[
[
0,
1335519666.31137,
0.000792741775512695
],
[
[
[
2
],
[
[
"_id",
"UInt32"
],
[
"_key",
"ShortText"
],
[
"body",
"ShortText"
]
],
[
1,
"001",
"すっぱいブドウと甘いシークァーサー"
],
[
2,
"002",
"シークヮーサージュースとゴーヤチャンプル"
]
]
]
]
> select Doc --match_columns body --query "シークヮーサー" --query_expansion Synonym.body
[
[
0,
1335519666.51486,
0.000669717788696289
],
[
[
[
2
],
[
[
"_id",
"UInt32"
],
[
"_key",
"ShortText"
],
[
"body",
"ShortText"
]
],
[
1,
"001",
"すっぱいブドウと甘いシークァーサー"
],
[
2,
"002",
"シークヮーサージュースとゴーヤチャンプル"
]
]
]
]
どちらのクエリ文字列も、"(シークァーサー OR シークヮーサー)"という文字列に置換されてから検索されるため、表記の揺れを吸収して検索できるようになりました。