バージョンごとのドキュメント一覧

12.1. はじめに #

<title>Introduction</title>

Full Text Searching (or just <firstterm>text search</firstterm>) provides the capability to identify natural-language <firstterm>documents</firstterm> that satisfy a <firstterm>query</firstterm>, and optionally to sort them by relevance to the query. The most common type of search is to find all documents containing given <firstterm>query terms</firstterm> and return them in order of their <firstterm>similarity</firstterm> to the query. Notions of <varname>query</varname> and <varname>similarity</varname> are very flexible and depend on the specific application. The simplest search considers <varname>query</varname> as a set of words and <varname>similarity</varname> as the frequency of query words in the document. 全文検索(または単にテキスト検索)は、問い合わせを満たす自然言語の文書を識別し、更には問い合わせとの関連性の順に並べ替えることができます。 もっとも一般的な検索は、与えられた検索語を含む文書を探し、問い合わせとの類似性の順に返す、というものです。 問い合わせ類似性の記法は非常に柔軟で、特定の用途に適合できます。 もっとも単純な検索では、問い合わせは単語の集合として、類似性は文書中の問い合わせ対象の単語の頻度として扱います。

Textual search operators have existed in databases for years. <productname>PostgreSQL</productname> has <literal>~</literal>, <literal>~*</literal>, <literal>LIKE</literal>, and <literal>ILIKE</literal> operators for textual data types, but they lack many essential properties required by modern information systems: テキスト検索演算子は、データベースシステムに長年存在していました。PostgreSQLは、テキストデータ型用に、~,~*, LIKE,ILIKEの各演算子を持っています。しかし、近代的な情報システムに必要な以下の本質的な特徴を欠いています。

Full text indexing allows documents to be <emphasis>preprocessed</emphasis> and an index saved for later rapid searching. Preprocessing includes: 全文検索のインデックス付けでは、文書を前もって処理しておき、後で素早く検索するために、インデックスを保存しておくことができます。前処理には以下があります。

Dictionaries allow fine-grained control over how tokens are normalized. With appropriate dictionaries, you can: 辞書を使ってトークンの正規化を細かく制御できます。 適当な辞書を用意すれば次のようなことができます。

A data type <type>tsvector</type> is provided for storing preprocessed documents, along with a type <type>tsquery</type> for representing processed queries (<xref linkend="datatype-textsearch"/>). There are many functions and operators available for these data types (<xref linkend="functions-textsearch"/>), the most important of which is the match operator <literal>@@</literal>, which we introduce in <xref linkend="textsearch-matching"/>. Full text searches can be accelerated using indexes (<xref linkend="textsearch-indexes"/>). 前処理した文書を格納するために、データ型tsvectorが提供されています。また、処理済問い合わせを表現するためにtsquery型も提供されています(8.11)。 これらのデータ型のために、多数の関数と演算子が利用できますが(9.13)、もっとも重要なのは、12.1.2で紹介している@@演算子です。 全文検索はインデックス(12.9)を使って高速化できます。

12.1.1. 文書とは何か? #

<title>What Is a Document?</title>

A <firstterm>document</firstterm> is the unit of searching in a full text search system; for example, a magazine article or email message. The text search engine must be able to parse documents and store associations of lexemes (key words) with their parent document. Later, these associations are used to search for documents that contain query words. 文書は全文検索システムにおける検索の単位です。 たとえば、雑誌記事やメールのメッセージです。 テキスト検索エンジンは、文書をパースし、語彙素(キーワード)とそれが含まれる親文書の関連を格納できなければなりません。 後で、この関連を使って問い合わせ語を含む文書を検索するのに使います。

For searches within <productname>PostgreSQL</productname>, a document is normally a textual field within a row of a database table, or possibly a combination (concatenation) of such fields, perhaps stored in several tables or obtained dynamically. In other words, a document can be constructed from different parts for indexing and it might not be stored anywhere as a whole. For example: 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 m.mid = d.did AND m.mid = 12;

注記

Actually, in these example queries, <function>coalesce</function> should be used to prevent a single <literal>NULL</literal> attribute from causing a <literal>NULL</literal> result for the whole document. 実際には、これらの例の問い合わせでは、coalesceを使って、一部NULLが含まれているためにドキュメント全体がNULLになってしまうのを防ぐべきです。

Another possibility is to store the documents as simple text files in the file system. In this case, the database can be used to store the full text index and to execute searches, and some unique identifier can be used to retrieve the document from the file system. However, retrieving files from outside the database requires superuser permissions or special function support, so this is usually less convenient than keeping all the data inside <productname>PostgreSQL</productname>. Also, keeping everything inside the database allows easy access to document metadata to assist in indexing and display. 別な方法としては、ファイルシステム上に文書を単純なテキストファイルとして格納することです。 この場合、データベースは、フルテキストインデックスを格納し、検索を実行するために使うことができます。ファイルシステムから文書を取り出すためには、何かのユニークな識別子を使います。 しかし、データベースの外にあるファイルを取り出すには、スーパーユーザの許可か、特殊な関数のサポートが必要です。そういうわけでたいていの場合はPostgreSQLの中にすべてのデータを保持するのよりも不便です。 また、すべてのデータをデータベースに保持することにより、文書のインデックス付けと表示の際に文書のメタデータにアクセスすることが容易になります。

For text search purposes, each document must be reduced to the preprocessed <type>tsvector</type> format. Searching and ranking are performed entirely on the <type>tsvector</type> representation of a document &mdash; the original text need only be retrieved when the document has been selected for display to a user. We therefore often speak of the <type>tsvector</type> as being the document, but of course it is only a compact representation of the full document. テキスト検索という目的のため、各々の文書は前処理されてtsvector形式に変換しておかなければなりません。 検索とランキングはすべて文書のtsvector表現上で実行されます — オリジナル文書は、ユーザに表示のため選択された場合にのみ取り出される必要があります。 というわけで、ここではtsvectorを文書と見なすことがよくあります。といっても、tsvectorは完全な文書の縮小表現でしかありません。

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

<title>Basic Text Matching</title>

Full text searching in <productname>PostgreSQL</productname> is based on the match operator <literal>@@</literal>, which returns <literal>true</literal> if a <type>tsvector</type> (document) matches a <type>tsquery</type> (query). It doesn't matter which data type is written first: PostgreSQLにおける全文検索は、tsvector(文書)が、tsquery(問い合わせ)に一致したらtrueを返す照合演算子@@に基づいています。どちらのデータ型を先に書いても構いません。

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

As the above example suggests, a <type>tsquery</type> is not just raw text, any more than a <type>tsvector</type> is. A <type>tsquery</type> contains search terms, which must be already-normalized lexemes, and may combine multiple terms using AND, OR, NOT, and FOLLOWED BY operators. (For syntax details see <xref linkend="datatype-tsquery"/>.) There are functions <function>to_tsquery</function>, <function>plainto_tsquery</function>, and <function>phraseto_tsquery</function> that are helpful in converting user-written text into a proper <type>tsquery</type>, primarily by normalizing words appearing in the text. Similarly, <function>to_tsvector</function> is used to parse and normalize a document string. So in practice a text search match would look more like this: 上記の例でわかるように、tsqueryは、tsvectorと違って、単なるテキストではありません。 tsqueryは正規化済の語彙素である検索表現を含み、AND, OR, NOT, FOLLOWED BY演算子を使って複数の表現を組み合わせても構いません。 (詳細は8.11.2を見てください。) 主にテキスト中の単語を正規化することにより、ユーザが入力したテキストを適切なtsqueryに変換するのに便利な関数to_tsqueryplainto_tsqueryphraseto_tsqueryがあります。 同様に、文書文字列をパースして正規化するためにto_tsvectorが利用できます。 というわけで、実際にはテキスト検索照合はこんな感じになります。

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

Observe that this match would not succeed if written as この照合は、もしつぎのように書くとうまくいかないことに注意してください。

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

since here no normalization of the word <literal>rats</literal> will occur. The elements of a <type>tsvector</type> are lexemes, which are assumed already normalized, so <literal>rats</literal> does not match <literal>rat</literal>. というのも、単語ratsに対して正規化が行われないからです。 tsvectorの要素は、すでに正規化されている語彙素であることになっているので、ratsratに一致しません。

The <literal>@@</literal> operator also supports <type>text</type> input, allowing explicit conversion of a text string to <type>tsvector</type> or <type>tsquery</type> to be skipped in simple cases. The variants available are: また、@@演算子は、textを入力として受付けるので、簡単に使うときには、明示的にテキスト文字列をtsvectorまたはtsqueryに変換することを省略できます。応用として以下のものがあります。

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

The first two of these we saw already. The form <type>text</type> <literal>@@</literal> <type>tsquery</type> is equivalent to <literal>to_tsvector(x) @@ y</literal>. The form <type>text</type> <literal>@@</literal> <type>text</type> is equivalent to <literal>to_tsvector(x) @@ plainto_tsquery(y)</literal>. 最初の2つについてはすでに説明しました。 text @@ tsqueryという形式は、to_tsvector(x) @@ yと同じです。 text @@ textという形式は、to_tsvector(x) @@plainto_tsquery(y)と同じです。

Within a <type>tsquery</type>, the <literal>&amp;</literal> (AND) operator specifies that both its arguments must appear in the document to have a match. Similarly, the <literal>|</literal> (OR) operator specifies that at least one of its arguments must appear, while the <literal>!</literal> (NOT) operator specifies that its argument must <emphasis>not</emphasis> appear in order to have a match. For example, the query <literal>fat &amp; ! rat</literal> matches documents that contain <literal>fat</literal> but not <literal>rat</literal>. tsquery内において、演算子 & (AND) は、マッチと見なされるには引数の両方がドキュメント内に現れる必要があるということを指定します。 同様に、演算子 | (OR) では、引数の少なくとも一方が現れる必要があり、また演算子 ! (NOT) は、マッチと見なされるには引数が現れてはならないことを指定します。 例えば、fat & ! ratという問い合わせは、fatは含むがratは含まないドキュメントとマッチします。

Searching for phrases is possible with the help of the <literal>&lt;-&gt;</literal> (FOLLOWED BY) <type>tsquery</type> operator, which matches only if its arguments have matches that are adjacent and in the given order. For example: 句の検索は、tsquery演算子 <-> (FOLLOWED BY)を使うことで可能です。 この演算子は、その引数にマッチする語が隣接していて、かつ指定と同じ順序である場合にのみマッチします。 例を示します。

SELECT to_tsvector('fatal error') @@ to_tsquery('fatal <-> error');
 ?column?
----------
 t

SELECT to_tsvector('error is not fatal') @@ to_tsquery('fatal <-> error');
 ?column?
----------
 f

There is a more general version of the FOLLOWED BY operator having the form <literal>&lt;<replaceable>N</replaceable>&gt;</literal>, where <replaceable>N</replaceable> is an integer standing for the difference between the positions of the matching lexemes. <literal>&lt;1&gt;</literal> is the same as <literal>&lt;-&gt;</literal>, while <literal>&lt;2&gt;</literal> allows exactly one other lexeme to appear between the matches, and so on. The <literal>phraseto_tsquery</literal> function makes use of this operator to construct a <literal>tsquery</literal> that can match a multi-word phrase when some of the words are stop words. For example: FOLLOWED BY演算子にはもっと汎用的なバージョンがあり、それは<N>という構文で使います。 ここでNは整数で、マッチする語彙素の位置の差を表します。 <1><->と同じですが、<2>ではマッチする語の間にちょうど1つ、他の語彙素が現れることを許容する、という具合です。 phraseto_tsquery関数は、この演算子を利用して、ストップワードを含む複数語の句にマッチ可能なtsqueryを構築するものです。 例を示します。

SELECT phraseto_tsquery('cats ate rats');
       phraseto_tsquery
-------------------------------
 'cat' <-> 'ate' <-> 'rat'

SELECT phraseto_tsquery('the cats ate the rats');
       phraseto_tsquery
-------------------------------
 'cat' <-> 'ate' <2> 'rat'

A special case that's sometimes useful is that <literal>&lt;0&gt;</literal> can be used to require that two patterns match the same word. ときに役立つことがある特別な場合として、<0>を2つのパターンが同じ語にマッチすることを要求するために使うことができます。

Parentheses can be used to control nesting of the <type>tsquery</type> operators. Without parentheses, <literal>|</literal> binds least tightly, then <literal>&amp;</literal>, then <literal>&lt;-&gt;</literal>, and <literal>!</literal> most tightly. tsquery演算子を入れ子にして管理するために括弧を使うことができます。 括弧がない場合、|の結合が最も弱く、次が&、その次が<->で、!が最も強く結合します。

It's worth noticing that the AND/OR/NOT operators mean something subtly different when they are within the arguments of a FOLLOWED BY operator than when they are not, because within FOLLOWED BY the exact position of the match is significant. For example, normally <literal>!x</literal> matches only documents that do not contain <literal>x</literal> anywhere. But <literal>!x &lt;-&gt; y</literal> matches <literal>y</literal> if it is not immediately after an <literal>x</literal>; an occurrence of <literal>x</literal> elsewhere in the document does not prevent a match. Another example is that <literal>x &amp; y</literal> normally only requires that <literal>x</literal> and <literal>y</literal> both appear somewhere in the document, but <literal>(x &amp; y) &lt;-&gt; z</literal> requires <literal>x</literal> and <literal>y</literal> to match at the same place, immediately before a <literal>z</literal>. Thus this query behaves differently from <literal>x &lt;-&gt; z &amp; y &lt;-&gt; z</literal>, which will match a document containing two separate sequences <literal>x z</literal> and <literal>y z</literal>. (This specific query is useless as written, since <literal>x</literal> and <literal>y</literal> could not match at the same place; but with more complex situations such as prefix-match patterns, a query of this form could be useful.) FOLLOWED BYの中ではマッチの正確な位置が重要ですので、AND/OR/NOT演算子は、FOLLOWED BY演算子の引数の中で使われる場合にはそうでない場合と微妙に異なる意味になることに言及しておく価値はあります。 例えば、通常!xxをどこにも含まない文書とのみマッチします。 しかし、!x <-> yは、xの直後にあるのでなければyとマッチします。文書の他のところでのxの出現は、マッチを邪魔しません。 もう一つの例は、x & yは通常xyの両方が文書のどこかに現れることだけを要求しますが、(x & y) <-> zは、xyが同じ場所、zの直前でマッチすることを要求します。 そのため、この問い合わせはx <-> z & y <-> zとは異なった振る舞いをします。後者は2つの別の文字列、x zy zを含む文書にマッチします。 (xyが同じ場所でマッチすることはあり得ませんので、上に書いたこの特別な問い合わせは、役に立ちません。しかし、接頭辞マッチパターンのようにより複雑な状況では、この形の問い合わせは役に立つかもしれません。)

12.1.3. 設定 #

<title>Configurations</title>

The above are all simple text search examples. As mentioned before, full text search functionality includes the ability to do many more things: skip indexing certain words (stop words), process synonyms, and use sophisticated parsing, e.g., parse based on more than just white space. This functionality is controlled by <firstterm>text search configurations</firstterm>. <productname>PostgreSQL</productname> comes with predefined configurations for many languages, and you can easily create your own configurations. (<application>psql</application>'s <command>\dF</command> command shows all available configurations.) 今までのはすべて単純なテキスト検索の例でした。 すでに述べたように、全文検索機能を使えば、もっと色々なことができます。 インデックス付けの際に特定の単語をスキップ(ストップワード)、同義語(synonym)処理、賢いパース処理、すなわち、単に空白区切りに基づくパース処理以上のものです。 この機能はテキスト検索設定で制御します。 PostgreSQLには、多くの言語用の設定があらかじめ組み込まれていますが、ユーザ設定を容易に作ることもできます。 (psql\dFコマンドで、利用できる設定を表示できます。)

During installation an appropriate configuration is selected and <xref linkend="guc-default-text-search-config"/> is set accordingly in <filename>postgresql.conf</filename>. If you are using the same text search configuration for the entire cluster you can use the value in <filename>postgresql.conf</filename>. To use different configurations throughout the cluster but the same configuration within any one database, use <command>ALTER DATABASE ... SET</command>. Otherwise, you can set <varname>default_text_search_config</varname> in each session. インストールの際には、適当な設定が選ばれ、default_text_search_configpostgresql.conf中にセットされます。 クラスタ全体で同じ設定を使用する場合はpostgresql.confの設定値を利用できます。 クラスタの設定とは異なるが、あるデータベースの中で同じ設定を使う場合には、ALTER DATABASE ... SETを利用します。 さもなければ、セッション単位でdefault_text_search_configを設定できます。

Each text search function that depends on a configuration has an optional <type>regconfig</type> argument, so that the configuration to use can be specified explicitly. <varname>default_text_search_config</varname> is used only when this argument is omitted. 設定に依存するテキスト検索関数は、オプションでregconfig引数を持っており、使用する設定を明示的に指定できます。default_text_search_configは、この引数が省略されたときだけ使用されます。

To make it easier to build custom text search configurations, a configuration is built up from simpler database objects. <productname>PostgreSQL</productname>'s text search facility provides four types of configuration-related database objects: カスタムテキスト検索設定を作り易くするため、設定はより単純なデータベースオブジェクトから作られます。PostgreSQLのテキスト検索機能は、4つの設定関連のデータベースオブジェクトを提供しています。

  • <firstterm>Text search parsers</firstterm> break documents into tokens and classify each token (for example, as words or numbers). テキスト検索パーサは、文書をトークンに分解し、トークンを分類します(たとえば、単語とか数のように)。

  • <firstterm>Text search dictionaries</firstterm> convert tokens to normalized form and reject stop words. テキスト検索辞書はトークンを正規化された形式に変換し、ストップワードを排除します。

  • <firstterm>Text search templates</firstterm> provide the functions underlying dictionaries. (A dictionary simply specifies a template and a set of parameters for the template.) テキスト検索テンプレートは、現在の辞書が利用する関数を提供します(辞書は、単にテンプレートと、その引数の集合を指定するだけです)。

  • <firstterm>Text search configurations</firstterm> select a parser and a set of dictionaries to use to normalize the tokens produced by the parser. テキスト検索設定は、パーサと使用する辞書の集合を選択し、パーサが生成したトークンを正規化します。

Text search parsers and templates are built from low-level C functions; therefore it requires C programming ability to develop new ones, and superuser privileges to install one into a database. (There are examples of add-on parsers and templates in the <filename>contrib/</filename> area of the <productname>PostgreSQL</productname> distribution.) Since dictionaries and configurations just parameterize and connect together some underlying parsers and templates, no special privilege is needed to create a new dictionary or configuration. Examples of creating custom dictionaries and configurations appear later in this chapter. テキスト検索パーサとテンプレートは、低レベルのC関数で作ります。したがって、新しく開発するためにはCのプログラミング能力と、データベースにインストールするためのスーパーユーザ権限が必要になります。 (PostgreSQLの配布物のcontrib/には、追加パーサとテンプレートの例があります。) 辞書と設定は、単に配下のパーサとテンプレートのパラメータを設定し、両者を結び付けるだけなので、新しい辞書と設定を作るために特別な権限は必要ありません。 この章の後でカスタム辞書と設定を作る例が登場します。