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

12.6. 辞書

辞書は、検索の対象とならない単語( ストップワード )を削除するために使われます。また、同じ単語から派生した異なる形態の単語が照合するようにするために、単語を 正規化 するためにも使われます。検索の品質を向上するという面以外にも、正規化とストップワードの削除は、 tsvector 表現の文書のサイズを小さくし、結果として性能を向上させます。正規化は常に言語学的な意味を持つとは限らず、通常は用途の意味論に依存します。

正規化の例を示します。

辞書は、トークンを入力し、以下を返すプログラムです。

PostgreSQL は、多くの言語に定義済の辞書を提供しています。 また、カスタムパラメータを使った新しい辞書を作るために使えるテンプレートもいくつかあります。 定義済の辞書のテンプレートについては、以下で述べています。 今あるテンプレートが適当でないのなら、新しいものを作ることもできます。例は、 PostgreSQL の配布物の contrib/ をご覧下さい。

テキスト検索設定は、パーサと、パーサの出力トークンを処理する辞書の集合を結び付けます。パーサが返却する各々のトークン型に対して、設定で辞書のリストを指定します。パーサがあるトークン型を見つけると、ある辞書が単語を認識するまでリスト中の辞書が順番に調べられます。 ストップワードであるか、あるいはどの辞書もトークンを認識しない場合はそれは捨てられ、インデックス付けや検索の対象となりません。 通常、非 NULL を返す最初の辞書の出力が結果を決めることになり、他の残りの辞書は参照されません。しかし、フィルタリング辞書は与えられたワードを変更し、それを続く辞書へ渡すことができます。

辞書をリストする一般的な方法は、まずもっとも範囲の狭い、特定用途向の辞書を配置し、次にもっと一般的な辞書を置き、最後に Snowball 語幹処理や simple 辞書のような、すべてを認識する非常に一般的な辞書を置くことです。 たとえば、天文学向の検索では( astro_en 設定)では、 asciiword (ASCII単語)型を天文学用語の同義語辞書、一般的な英語辞書、そして Snowball 英語語幹辞書に結び付けることができます。

ALTER TEXT SEARCH CONFIGURATION astro_en
    ADD MAPPING FOR asciiword WITH astrosyn, english_ispell, english_stem;

フィルタリング辞書は、リスト中の好きな場所へ配置できます。(役に立たなくなるリストの最後を除きます。) フィルタリング辞書は、後続の辞書の処理を単純化するために、一部の文字の正規化を行うのに有用です。 例えば、フィルタリング辞書は unaccent モジュールで実施される様な、アクセント記号が付与された文字からアクセント記号を取り除くのに使用することができます。

12.6.1. ストップワード

ストップワードは、ほとんどすべての文書に現れるような非常に一般的で、ほかのものと同じようには扱う価値のない単語です。 ですから、全文検索の際には無視して構いません。 たとえば、すべての英語のテキストは a the のような単語を含んでおり、インデックスの中にそれらを入れても役に立ちません。 しかし、ストップワードは tsvector 中の位置に影響を与えるので、結局ランキングにも影響があります。

SELECT to_tsvector('english','in the list of stop words');
        to_tsvector
----------------------------
 'list':3 'stop':5 'word':6

位置1, 2, 4は、ストップワードのために失われています。ストップワード有無により、文書のために計算されたランクは非常に影響を受けます。

SELECT ts_rank_cd (to_tsvector('english','in the list of stop words'), to_tsquery('list & stop'));
 ts_rank_cd
------------
       0.05

SELECT ts_rank_cd (to_tsvector('english','list stop words'), to_tsquery('list & stop'));
 ts_rank_cd
------------
        0.1

ストップワードをどのように扱うかは、特定の辞書に任されています。 例えば、 ispell 辞書はまず単語を正規化し、そして、ストップワードのリストを検索します。一方、 Snowball 語幹抽出はまずストップワードのリストを検査します。 動作が異なる理由は、ノイズが紛れ込む可能性を減らすことです。

12.6.2. simple辞書

simple 辞書テンプレートは、入力トークンを小文字に変換し、ストップワードのファイルに対してチェックすることによって動作します。 もしファイルの中にあれば、空の配列が返却され、そのトークンは捨てられます。 そうでないときは、小文字形式の単語が正規化された語彙素として返却されます。 別の方法としては、ストップワードではないものは、認識できないものとすることもできます。そうすることにより、それらをリスト中の次の辞書に渡すことができます。

simple テンプレートを使った辞書定義の例を示します。

CREATE TEXT SEARCH DICTIONARY public.simple_dict (
    TEMPLATE = pg_catalog.simple,
    STOPWORDS = english
);

ここで、 english は、ストップワードファイルのベースネームです。 ファイルのフルネームは、 $SHAREDIR/tsearch_data/english.stop です。 $SHAREDIR は、 PostgreSQL インストール先の共有データディレクトリです。これは、よく /usr/local/share/postgresql に置いてあります。(良くわからない場合は pg_config --sharedir を使ってください)。 ファイル形式は、単に1行ごとに単語を書くだけです。 空行と、後方の空白は無視されます。大文字は小文字に変換されます。このファイルの内容に関する処理はこれだけです。

これで辞書のテストができます。

SELECT ts_lexize('public.simple_dict','YeS');
 ts_lexize
-----------
 {yes}

SELECT ts_lexize('public.simple_dict','The');
 ts_lexize
-----------
 {}

また、ストップワードファイルの中に見つからないときに、小文字に変換した単語を返す代わりに、 NULL を返すことを選ぶこともできます。 この挙動は、辞書の Accept パラメータを false に設定することで選択されます。 さらに例を続けます。

ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false );

SELECT ts_lexize('public.simple_dict','YeS');
 ts_lexize
-----------


SELECT ts_lexize('public.simple_dict','The');
 ts_lexize
-----------
 {}

デフォルト設定の Accept = true では、 simple 辞書は、辞書リストの最後に置かなければ意味がありません。なぜなら、後続の辞書にトークンを渡すことがないからです。逆に Accept = false は、後続の辞書が少なくとも一つはあるときに意味があります。

注意

ほとんどの辞書の形式は、ストップワードファイルのように設定ファイルに依存します。これらのファイルは 必ず UTF-8エンコーディングにしてください。サーバのエンコーディングがUTF-8でない場合は、サーバに読み込まれる際に実際のデータベースエンコーディングに変換されます。

注意

通常、辞書はデータベースセッションの中で最初に使われる際に、一度だけ読み込まれます。辞書を変更し、現在使われているセッションの中で新しい内容が読み込まれるようにしたい場合は、その辞書に対して ALTER TEXT SEARCH DICTIONARY を発行してください。これは実際にはどんなパラメータ値をも変更しない "ダミー" の更新でよいです。

12.6.3. 同義語辞書

この辞書テンプレートは、単語を同義語に置き換える辞書を作るために使われます。語句はサポートされていません(そのためには類語テンプレート( 項12.6.4 )を使ってください)。同義語辞書は、言語学的な問題、たとえば、英語語幹辞書が "Paris" という単語を "pari" に縮小してしまうのを防ぎます。 Paris paris という行を同義語辞書に登録し、 english_stem 辞書の前に置くようにするだけでよいのです。下記はその例です。

SELECT * FROM ts_debug('english', 'Paris');
   alias   |   description   | token |  dictionaries  |  dictionary  | lexemes 
-----------+-----------------+-------+----------------+--------------+---------
 asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari}

CREATE TEXT SEARCH DICTIONARY my_synonym (
    TEMPLATE = synonym,
    SYNONYMS = my_synonyms
);

ALTER TEXT SEARCH CONFIGURATION english
    ALTER MAPPING FOR asciiword
    WITH my_synonym, english_stem;

SELECT * FROM ts_debug('english', 'Paris');
   alias   |   description   | token |       dictionaries        | dictionary | lexemes 
-----------+-----------------+-------+---------------------------+------------+---------
 asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris}

synonym テンプレートに必要なパラメータは SYNONYMS だけで、その設定ファイルのベースネームです — 上の例では my_synonyms です。 ファイルのフルネームは、 $SHAREDIR/tsearch_data/my_synonyms.syn となります(ここで $SHAREDIR は、 PostgreSQL をインストールした際の、共有データディレクトリです)。 ファイルの形式は、置き換え対象の1単語につき1行で、単語には空白で区切られた同義語が後に続きます。 空行、後方の空白は無視されます。

synonym テンプレートはまた、 CaseSensitive というオプションパラメータを持っており、デフォルトは false です。 CaseSensitive false の時は、同義語辞書内の単語は入力トークンと同様に小文字に変換されます。 true の時は、単語とトークンは小文字に変換されずそのまま比較されます。

アスタリスク( * )は設定ファイル中の同義語の最後に付与することができます。 これは同義語を接頭語とすることを意味します。 アスタリスクは、エントリが to_tsvector() で使用される場合には無視されますが、 to_tsquery() で使用される場合、結果は前方一致を伴った問い合わせになるでしょう。(詳しくは 項12.3.2 を見てください。) 例えば、 $SHAREDIR/tsearch_data/synonym_sample.syn に以下の様なエントリをもっていたとします。

postgres        pgsql
postgresql      pgsql
postgre pgsql
gogle   googl
indices index*

この場合、次のような結果を得ることになります。

mydb=# CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample');
mydb=# SELECT ts_lexize('syn','indices');
 ts_lexize
-----------
 {index}
(1 row)

mydb=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple);
mydb=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn;
mydb=# SELECT to_tsvector('tst','indices');
 to_tsvector
-------------
 'index':1
(1 row)

mydb=# SELECT to_tsquery('tst','indices');
 to_tsquery
------------
 'index':*
(1 row)

mydb=# SELECT 'indexes are very useful'::tsvector;
            tsvector             
---------------------------------
 'are' 'indexes' 'useful' 'very'
(1 row)

mydb=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst','indices');
 ?column?
----------
 t
(1 row)

12.6.4. 類語辞書

類語辞書( TZ と略されることがあります)は、単語と語句の関係情報を集めたものです。つまり、広義用語( BT )、狭義用語( NT )、優先用語、非優先用語、関連用語などです。

基本的には、類語辞書は、非優先用語を優先用語に置き換え、オプションで元の用語もインデックス付けのため保存します。 PostgreSQL の現在の類語辞書の実装は、同義語辞書を拡張し、 語句 のサポートを追加したものです。類語辞書は、以下のようなフォーマットの設定ファイルを必要とします。

# this is a comment
sample word(s) : indexed word(s)
more sample word(s) : more indexed word(s)
...

ここで、コロン( : )は、語句とその置き換え対象の区切りです。

類語辞書は、 副辞書 (辞書設定で指定します)を、一致する語句をチェックする前に入力テキストを正規化するために使います。 副辞書はただ一つだけ選べます。 副辞書が単語を認識できない場合はエラーが報告されます。 その場合は、その単語の利用を止めるか、副辞書にそのことを教えなければなりません。 アスタリスク( * )をインデックス付けされた単語の先頭に置くことにより、副辞書の適用をスキップできます。しかしながら、すべてのサンプルの単語は、副辞書に認識 されなければなりません

複数の類語が照合するときは、類語辞書はもっとも長いものを選びます。そして、語句は、最後の定義を使って分解されます。

特定のストップワードを副辞書に認識するように指定することはできません。その代わり、ストップワードが出現する位置を ? でマークします。 たとえば、 a the が副辞書によればストップワードだったとします。

? one ? two : swsw

は、 a one the two the one a two に照合します。そして、両方とも swsw に置き換えられます。

類語辞書は語句を認識することができるので、状態を記憶してパーサと連携を保たなければなりません。 類語辞書は、この機能を使って次の単語を引き続き処理するのか、単語の蓄積を止めるのかを決定します。 類語辞書の設定は注意深く行わなければなりません。 たとえば、類語辞書が asciiword トークンだけを扱うようになっている場合、 one 7 のような類語辞書の定義は、トークン型 uint が類語辞書にアサインされていないので動きません。

注意

類語辞書はインデックス付けの際に利用されるので、類語辞書を設定変更すると、再インデックス付けが 必要 になります。他のほとんどの辞書では、ストップワードを追加あるいは削除するような小さな変更は、インデックス付けを必要としません。

12.6.4.1. 類語設定

新しい類語辞書を定義するには、 thesaurus テンプレートを使います。例を示します。

CREATE TEXT SEARCH DICTIONARY thesaurus_simple (
    TEMPLATE = thesaurus,
    DictFile = mythesaurus,
    Dictionary = pg_catalog.english_stem
);

ここで、

  • thesaurus_simple は新しい辞書の名前です。

  • mythesaurus は、類語設定ファイルのベースネームです。 (フルパスは、 $SHAREDIR/tsearch_data/mythesaurus.ths となります。ここで、 $SHAREDIR はインストール時の共有データディレクトリです。)

  • 類語正規化で使用する pg_catalog.english_stem は副辞書です(ここでは、Snowball英語語幹辞書)。 副辞書にはそれ用の設定(たとえばストップワード)があることに注意してください。ここではそれは表示していません。

これで、類語辞書 thesaurus_simple を、設定中の希望のトークンにバインドすることができるようになります。例を示します。

ALTER TEXT SEARCH CONFIGURATION russian
    ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
    WITH thesaurus_simple;

12.6.4.2. 類語の例

天文学の単語の組合わせを含む単純な天文学用の thesaurus_astro 類語を考えます。

supernovae stars : sn
crab nebulae : crab

以下で辞書を作り、トークン型を天文学類語辞書と英語の語幹辞書に結び付けます。

CREATE TEXT SEARCH DICTIONARY thesaurus_astro (
    TEMPLATE = thesaurus,
    DictFile = thesaurus_astro,
    Dictionary = english_stem
);

ALTER TEXT SEARCH CONFIGURATION russian
    ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
    WITH thesaurus_astro, english_stem;

さあ、これでどのように動くか試せます。 ts_lexize は類語をテストする目的にはあまり有用ではありません。なぜなら、それは入力を単一のトークンとして扱うからです。 その代わりに、 plainto_tsquery to_tsvector を使って入力文字列を複数のトークンに分解します。

SELECT plainto_tsquery('supernova star');
 plainto_tsquery
-----------------
 'sn'

SELECT to_tsvector('supernova star');
 to_tsvector
-------------
 'sn':1

原則として、引数を引用符で囲めば to_tsquery が使えます。

SELECT to_tsquery('''supernova star''');
 to_tsquery
------------
 'sn'

english_stem 語幹辞書を同義語辞書の定義時に指定したので、 supernova star thesaurus_astro 中の supernovae stars に照合していることに注意してください。 語幹処理が e s を削除しています。

置き換え後の語句とオリジナルの語句の両方をインデックス付けするには、定義の右項にオリジナルを追加するだけで良いです。

supernovae stars : sn supernovae stars

SELECT plainto_tsquery('supernova star');
       plainto_tsquery
-----------------------------
 'sn' & 'supernova' & 'star'

12.6.5. Ispell 辞書

Ispell 辞書テンプレートは、 形態論辞書 を提供します。これによって、言語学的に多様な単語の形態を同じ語彙素に変換することができます。 たとえば、英語 Ispell 辞書は、検索語 bank の語形変化と活用変化、たとえば banking , banked , banks , banks' , bank's に照合します。

PostgreSQL の標準配布には、 Ispell の設定ファイルは含まれていません。 多くの言語用の辞書が Ispell で入手できます。 また、より新しい辞書のフォーマットもサポートされています — MySpell (OO < 2.0.1)と Hunspell (OO >= 2.0.2)。 多数の辞書のリストが OpenOffice Wiki で入手できます。

Ispell 辞書を作るには、組み込みの ispell テンプレートを使い、いくつかパラメータを指定します。

CREATE TEXT SEARCH DICTIONARY english_ispell (
    TEMPLATE = ispell,
    DictFile = english,
    AffFile = english,
    StopWords = english
);

ここで、 DictFile , AffFile , および StopWords は、辞書のベースネーム、接辞ファイル、ストップワードファイルを指定します。 ストップワードファイルは、上で説明した simple 辞書と同じ形式です。 ほかのファイルの形式はここでは説明されませんが、上にあげたウェブサイトに説明があります。

Ispell辞書は通常限られた数の単語を認識します。ですので、なんでも認識できるSnowball辞書のような、より適用範囲の広い辞書による後処理が必要です。

Ispell辞書を使って複合語を分割することができます。これは優れた機能です。 接辞ファイルは、複合語形式の候補になる辞書中の単語に印を付ける compoundwords controlled 文を使う特別なフラグを指定しなければならないことに注意してください。

compoundwords  controlled z

ノルウェー語の例をいくつか示します。

SELECT ts_lexize('norwegian_ispell', 'overbuljongterningpakkmesterassistent');
   {over,buljong,terning,pakk,mester,assistent}
SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk');
   {sjokoladefabrikk,sjokolade,fabrikk}

注意: MySpell は複合語をサポートしていません。 Hunspell は複合語の高度なサポートを提供しています。いまのところ、 PostgreSQL はHunspellの基本的な複合語操作しかサポートしていません。

12.6.6. Snowball 辞書

Snowball 辞書テンプレートは、有名な「英語用のポーターの語幹アルゴリズム」を発明したMartin Porterのプロジェクトに基づいています。Snowballは今では多くの言語用の語幹アルゴリズムを提供しています(詳細は Snowballのサイト を参照してください)。各々のアルゴリズムにより、その言語において単語の共通部分を取りだし、基本部もしくは語幹の綴りに縮退させることができます。Snowball辞書には、どの語幹処理を使うかを識別する 言語 パラメータが必須で、加えて、オプションで無視すべき単語のリストを保持する ストップワード ファイルを指定することもできます。( PostgreSQL の標準的なストップワードファイルもまたSnowball projectから提供されています)。たとえば、以下と同じ組み込みの定義があります。

CREATE TEXT SEARCH DICTIONARY english_stem (
    TEMPLATE = snowball,
    Language = english,
    StopWords = english
);

ストップワードファイルの形式はすでに説明されているものと同じです。

Snowball 辞書は、単純化できるかどうかに関係なく、すべての単語を認識するので、辞書リストの最後に置く必要があります。他の辞書の前に置くのは意味がありません。 Snowball 辞書は決してトークンを次の辞書に渡さないからです。


powered by SEO.CUG.NET