ファイルサーバをPostgreSQL8.3で全文検索するというのを,相変わらず色々やっている.日本語の文書の場合,英数字が全角で書かれている場合があるが,検索したときは全角も半角も同じようにヒットして欲しい.

つまり「Apache」で検索したときは,「Apache」も「Apache」も両方ヒットしなければ困る.

これを実現するためには,文書をインデックス化するときに英字を半角変換すればよい.

そのために, は以下のような方法を採っている.

インデックス作成

create or replace  function zenkakuToHankaku(
	in i_zenstr text) returns text immutable as $$
declare
	v_hanstr    text;
begin
	v_hanstr := translate(i_zenstr, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
	v_hanstr := translate(v_hanstr, 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz');
	v_hanstr := translate(v_hanstr, '1234567890', '1234567890');
	v_hanstr := translate(v_hanstr, ' ', ' ');
	return v_hanstr;
end
$$ language plpgsql;

CREATE INDEX file_item_z1 ON file_item USING gin (to_tsvector('english', wakachi(zenkakuToHankaku(contents))));

検索

SELECT
	file_path
FROM
	file_item,
	to_tsquery('pg_catalog.english', zenkakuToHankaku(?)) query
WHERE
	query @@ to_tsvector('english',wakachi(zenkakuToHankaku(contents)));

インデックス化の前処理Functionとして,zenkakuToHankaku()を作成し,これで半角変換を行っている.

このFunctionは,「immutable」に指定しないと検索時にインデックスが効かなくなるので注意が必要. まぁFunctionインデックスみたいな用法なので,そういうものなのでしょう.

余談だが,PostgreSQL用全文検索関連ソフトウェア SRA OSSには,normalizeというまさにうってつけのC言語関数が公開されているが,しかしこれはEUC-JP用だった.orz 今回はUTF-8でやっているのでした.

...まぁ,これで一応目的は達成できてちゃんと動いているのだが,どうも間抜けな気がする. こういう汎用的な処理をわざわざFunctionを作って行っているというところに,違和感を感じる.

それでマニュアルを見ると

12.6.2. Simple Dictionary
に,
The simple dictionary template operates by converting the input token to
lower case and checking it against a file of stop words.
という記述があるので,本来はこのような変換は,Dictionary Templateで行うらしい.

また,

12.6. Dictionaries
には,
If no existing template is suitable, it is possible to create new ones;
see the contrib/ area of the PostgreSQL distribution for examples.
という記述があるので,自分でC言語で作成できるようだ.

う〜む.そこまで手を染めるべきなのだろうか.


© 2024 KMIソフトウェア