無料スクリプト配布のPHP.TO   PHPの実用的なtips PHPマニュアル MySQLマニュアル Apacheマニュアル PostgreSQLマニュアル マニュアル検索    

12.1. 導入

全文検索(または単に テキスト検索 )は、 問合わせ を満たす自然言語の文書を識別し、更には問合わせとの関連性の順に並び替えることができます。 もっとも一般的な検索は、与えられた 検索語 を含む文書を探し、 問合わせ との 類似性 の順に返す、というものです。 問合わせ 類似性 の記法は非常に柔軟で、特定の用途に適合できます。 もっとも単純な検索では、 問合わせ は単語の集合として、 類似性 は文書中の問合わせ対象の単語の頻度として扱います。

テキスト検索演算子は、データベースシステムに長年存在していました。 PostgreSQL は、テキストデータ型用に、 ~ , ~* , LIKE , ILIKE の各演算子を持っています。しかし、近代的な情報システムに必要な以下の本質的な特徴を欠いています。

全文検索のインデックス付けでは、文書を 前もって処理しておき 、後で素早く検索するために、インデックスを保存しておくことができます。前処理には以下があります。

辞書を使ってトークンの正規化を細かく制御できます。 適当な辞書を用意すれば次のようなことができます。

前処理した文書を格納するために、データ型 tsvector が提供されています。また、処理済問合わせを表現するために tsquery 型も提供されています( 項8.11 )。これらのデータ型のために、多数の関数と演算子が利用できますが( 項9.13 )、もっとも重要なのは、 項12.1.2 で紹介している @@ 演算子です。全文検索はインデックス( 項12.9 )を使って高速化できます。

12.1.1. 文書とは何か?

文書 は全文検索システムにおける検索の単位です。 たとえば、雑誌記事やメールのメッセージです。 テキスト検索エンジンは、文書をパースし、語彙素(キーワード)とそれが含まれる親文書の関連を格納できなければなりません。 後で、この関連を使って問合わせ語を含む文書を検索するのに使います。

PostgreSQL での検索においては、ドキュメントはデータベースのテーブルの行内のテキストフィールドか、あるいはそのようなフィールドの組み合わせ(結合)でもよいです。そうしたフィールドはおそらく複数のテーブルに格納されていたり、動的に獲得されるものであったりします。 言い換えると、文書はインデックス付けのために複数の異なる部分から構成されても良く、それらが全体としてはひとまとまりに格納されていなくても良いのです。例を示します。

SELECT title || ' ' ||  author || ' ' ||  abstract || ' ' || body AS document
FROM messages
WHERE mid = 12;

SELECT m.title || ' ' || m.author || ' ' || m.abstract || ' ' || d.body AS document
FROM messages m, docs d
WHERE mid = did AND mid = 12;

注意: 実際には、これらの例の問合わせでは、 coalesce を使って、一部NULLが含まれているためにドキュメント全体がNULLになってしまうのを防ぐべきです。

別な方法としては、ファイルシステム上に文書を単純なテキストファイルとして格納することです。この場合、データベースは、フルテキストインデックスを格納し、検索を実行するために使うことができます。ファイルシステムから文書を取り出すためには、何かのユニークな識別子を使います。しかし、データベースの外にあるファイルを取り出すには、スーパユーザの許可か、特殊な関数のサポートが必要です。そういうわけでたいていの場合は PostgreSQL の中にすべてのデータを保持するのよりも不便です。また、すべてのデータをデータベースに保持することにより、文書のインデックス付けと表示の際に文書のメタデータにアクセスすることが容易になります。

テキスト検索という目的のため、各々の文書は前処理されて tsvector 形式に変換しておかなければなりません。検索と順位付けはすべて tsvector 表現の文書上で行われます。検索とランキングは文書の tsvector 表現上で実行されます — オリジナル文書は、ユーザに表示のため選択された場合にのみ取り出される必要があります。というわけで、ここでは tsvector を文書と見なすことがよくあります。といっても、 tsvector は完全な文書の縮小表現でしかありません。

12.1.2. 基本的なテキスト照合

PostgreSQL における全文検索は、 tsvector (文書)が、 tsquery (問合わせ)に一致したら真を返す照合演算子 @@ に基づいています。どちらのデータ型を先に書いても構いません。

SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery;
 ?column?
----------
 t

SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector;
 ?column?
----------
 f

上記の例でわかるように、 tsquery は、 tsvector と違って、単なるテキストではありません。 tsquery は正規化済の語彙素である検索表現を含み、AND, OR, NOT演算子を使って複数の表現を組み合わせても構いません。 (詳細は 項8.11 これを見てください。) たとえば、テキスト中の単語を正規化することにより、ユーザが入力したテキストを適切な tsquery に変換する to_tsquery plainto_tsquery という関数があります。同様に、文書文字列をパースして正規化するために to_tsvector が利用できます。 というわけで、実際にはテキスト検索照合はこんな感じになります。

SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat');
 ?column? 
----------
 t

この照合は、もしつぎのように書くとうまくいかないことに注意してください。

SELECT 'fat cats ate fat rats'::tsvector @@ to_tsquery('fat & rat');
 ?column? 
----------
 f

というのも、単語 rats に対して正規化が行われないからです。 tsvector の要素は、すでに正規化されている語彙素であることになっているので、 rats rat に一致しません。

また、 @@ 演算子は、 text を入力として受付けるので、簡単に使うときには、明示的にテキスト文字列を tsvector または tsquery に変換することを省略できます。応用として以下のものがあります。

tsvector @@ tsquery
tsquery  @@ tsvector
text @@ tsquery
text @@ text

最初の2つについてはすでに説明しました。 text @@ tsquery という形式は、 to_tsvector(x) @@ y と同じです。 text @@ text という形式は、 to_tsvector(x) @@plainto_tsquery(y) と同じです。

12.1.3. 設定

今までのはすべて単純なテキスト検索の例でした。 すでに述べたように、全文検索機能を使えば、もっと色々なことができます。 インデックス付けの際に特定の単語をスキップ(ストップワード)、同義語(synonym)処理、賢いパース処理、すなわち、単に空白区切りに基づくパース処理以上のものです。 この機能は テキスト検索設定 で制御します。 PostgreSQL には、多くの言語用の設定があらかじめ組み込まれていますが、ユーザ設定を容易に作ることもできます。( psql \dF コマンドで、利用できる設定を表示できます。

インストールの際には、適当な設定が選ばれ、 default_text_search_config postgresql.conf 中にセットされます。クラスタ全体で同じ設定を使用する場合は postgresql.conf の設定値を利用できます。クラスタの設定とは異なるが、あるデータベースの中で同じ設定を使う場合には、 ALTER DATABASE ... SET を利用します。さもなければ、セッション単位で default_text_search_config を設定できます。

設定に依存するテキスト検索関数は、オプションで regconfig 引数を持っており、使用する設定を明示的に指定できます。 default_text_search_config は、この引数が省略されたときだけ使用されます。

カスタムテキスト検索設定を作り易くするため、設定はより単純なデータベースオブジェクトから作られます。 PostgreSQL のテキスト検索機能は、4つの設定関連のデータベースオブジェクトを提供しています。

  • テキスト検索パーサ は、文書をトークンに分解し、トークンを分類します(たとえば、単語とか数のように)。

  • テキスト検索辞書 はトークンを正規化された形式に変換し、ストップワードを排除します。

  • テキスト検索テンプレート は、現在の辞書が利用する関数を提供します(辞書は、単にテンプレートと、その引数の集合を指定するだけです)。

  • テキスト検索設定 は、パーサと使用する辞書の集合を選択し、パーサが生成したトークンを正規化します。

テキスト検索パーサとテンプレートは、低レベルのC関数で作ります。したがって、新しく開発するためにはCのプログラミング能力と、データベースにインストールするためのスーパユーザ権限が必要になります。( PostgreSQL の配布物の contrib/ には、追加パーサとテンプレートの例があります)。辞書と設定は、単に配下のパーサとテンプレートのパラメータを設定し、両者を結び付けるだけなので、新しい辞書と設定を作るために特別な権限は必要ありません。この章の後でカスタム辞書と設定を作る例が登場します。


powered by SEO.CUG.NET