textsearch-ja ホームページへようこそ


形態素解析を使用した、組み込み型の日本語全文検索です。

この textsearch-ja プロジェクトは PostgreSQL コミュニティによる pgFoundry の中のプロジェクトです。

Here is an English page.

  1. 概要
  2. インストール
  3. テキスト検索機能
  4. その他の検索用関数
  5. 日本語解析機能
  6. TODO
  7. 関連リンク

概要

日本語テキストの全文検索を行います。 PostgreSQL 8.3 で追加された組み込みテキスト検索を拡張するため、 英語文書の検索と同様の方法で、日本語文書を検索することができます。 検索は形態素解析を利用した単語単位で行われます。 形態素解析には MeCab を使用しています。

利点として、GIN または GiST インデックスをベースにしているため、全文検索用のインデックスがリカバリ可能であることが挙げられます。 また、既に tsearch2 に対応している欧米言語を対象とした製品を大きく改変することなく、日本語対応できる強みがあります。

インストール

依存関係

以下の外部プロジェクトに依存しています。

MeCab

Windows 版のインストーラを使う場合、辞書の文字コードの選択 で UTF-8 を選んでください。 mecab-dict-index で辞書を再編成することもできます。 詳しくは MeCab のマニュアルを参照してください。

テキスト検索機能

インストールすると、pg_catalog.japanese という名前のテキスト検索設定が登録されます。 以下の形式で使用します。

入力テキストは、まず、後述の ja_normalize() 関数を使用して正規化されます。 正規化後の文字列に対して、形態素解析で単語を分割してインデックスを張ります。

サーバエンコーディングと、mecab のエンコーディングを一致させる必要があります。 プラットホームによっては、mecab 辞書の再コンパイルが必要になるかもしれません。

インデックス (tsvector, tsquery)

textsearch では、関数インデックスを使用して直接検索する方式と、 追加した補助カラムをキーとして検索する方式があります。 詳しくはドキュメント Full Text Search/Creating Indexes を参照してください。 補助カラムの自動更新は、tsvector_update_trigger に任せることもできます。

=# CREATE TABLE test (id serial, t text);
=# COPY test(t) FROM '...';
=# CREATE INDEX idx ON test USING gin(to_tsvector('japanese', t));
=# ANALYZE;
=# EXPLAIN SELECT * FROM test WHERE to_tsvector('japanese', t) @@ to_tsquery('japanese', 'リレーショナルデータベース');
                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Index Scan using idx on test  (cost=0.00..8.27 rows=1 width=248)
   Index Cond: (to_tsvector('japanese'::regconfig, t) @@ '''リレーショナル'' & ''データベース'''::tsquery)
(2 rows)

検索結果の強調 (ts_headline)

ts_headline() に対応しており、一致した箇所を切り出して強調表示できます。
=# \d document
                         Table "public.document"
 Column |   Type   |                      Modifiers
--------+----------+-------------------------------------------------------
 id     | integer  | not null default nextval('document_id_seq'::regclass)
 body   | text     |
 tsv    | tsvector |
Indexes:
    "document_pkey" PRIMARY KEY, btree (id)
    "document_tsv_index" gin (tsv)
Triggers:
    tsv_trigger BEFORE INSERT OR UPDATE ON document FOR EACH ROW EXECUTE PROCEDURE
      tsvector_update_trigger('tsv', 'pg_catalog.japanese', 'body')

=# SELECT id, ts_rank_cd(tsv, query) AS rank, ts_headline('japanese', body, query)
     FROM document, to_tsquery('japanese', 'リーフページ') AS query
    WHERE tsv @@ query ORDER BY rank DESC;
 id |   rank   |                                                                 ts_headline
----+----------+----------------------------------------------------------------------------------------------------------------------------------------------
  3 | 0.108333 | <b>ページ</b>中で隣接しているキーである。これは非ユニークキーに対しては動作しない ( たとえば、いくつかの<b>リーフ</b><b>ページ</b>にまたがっ
  2 |     0.01 | <b>ページ</b>を指しているはずである。同じ方法で、つまりヒープタプルへのリンクを調査することで、<b>リーフ</b>レベルにある複数の item
(2 rows)

解析結果の表示 (ts_debug)

=# SELECT * FROM ts_debug('japanese', '日本語とEnglishがmixedな文も解析OKです。');
   alias   |    description    |  token  |  dictionaries  |  dictionary  |  lexemes
-----------+-------------------+---------+----------------+--------------+-----------
 word      | Word, all letters | 日本語  | {simple}       | simple       | {日本語}
 blank     | Space symbols     | と      | {}             |              |
 asciiword | Word, all ASCII   | English | {english_stem} | english_stem | {english}
 blank     | Space symbols     | が      | {}             |              |
 asciiword | Word, all ASCII   | mixed   | {english_stem} | english_stem | {mix}
 blank     | Space symbols     | な      | {}             |              |
 word      | Word, all letters | 文      | {simple}       | simple       | {文}
 blank     | Space symbols     | も      | {}             |              |
 word      | Word, all letters | 解析    | {simple}       | simple       | {解析}
 asciiword | Word, all ASCII   | OK      | {english_stem} | english_stem | {ok}
 blank     | Space symbols     | です    | {}             |              |
 blank     | Space symbols     | 。      | {}             |              |
(12 rows)

類義語 (synonym)

類義語辞書を使用できます。 <インストール先>/share/tsearch_data/japanese.syn というテキストファイルを用意します。 文字エンコーディングは UTF-8 でなければなりません。

 バキューム	vacuum
 ポスグレ	pgsql
類義語辞書は、以下のSQLを使って登録します。
-- Install japanese synonym dictionary
CREATE TEXT SEARCH DICTIONARY japanese_syn (
    TEMPLATE = synonym,
    SYNONYMS = japanese
);
ALTER TEXT SEARCH CONFIGURATION japanese
    ALTER MAPPING FOR word, hword_part, hword WITH japanese_syn, simple;

類義語は変換して処理されるため、表記に揺れがあっても検索や強調ができます。

=# SELECT ts_headline('japanese', 'autovacuumを使えばバキュームも手間要らず',  to_tsquery('japanese', 'VACUUM'));
                   ts_headline
-------------------------------------------------
 autovacuumを使えば<b>バキューム</b>も手間要らず
(1 row)

同様に、$PGDATA/share/tsearch_data/english.syn を用意すれば、 英語の類義語辞書も同時に使用できます。 このとき、英語と日本語で必ずしも *.syn を分ける必要はありませんが、 英数字(半角)には必ず英語辞書が使われ、 日本語文字(全角)には必ず日本語辞書が使われるため、 分割したほうが若干変換速度が向上します。

-- Install english synonym dictionary
CREATE TEXT SEARCH DICTIONARY english_syn (
    TEMPLATE = synonym,
    SYNONYMS = english
);
ALTER TEXT SEARCH CONFIGURATION japanese
    ALTER MAPPING FOR asciiword, hword_asciipart, asciihword WITH english_syn, english_stem;

ストップワード (stop word)

現在、以下の品詞はストップワード(blank)とみなし、インデックス化していません。 不必要なインデックス・エントリを減らせるため、単純なスペース区切りによる分かち書きよりも効率が高まります。

実際には、類義語辞書と同じ方式で、textsearch 機能のストップワード辞書機能を使うことも可能です。 ただし、既に MeCab により単語区分が分かっているため、辞書よりも先に判定を行っています。 将来のバージョンでは、動作を選択可能にすることを考えています。

その他の検索用関数

Web検索互換クエリ (web_query)

textsearch は AND, OR, NOT 検索に &, |, ! を使用しています。 ウェブ検索で一般的に使用される制御演算子とは異なるため、検索フォームへの入力をそのまま条件に使用するには不便です。 関数 web_query() は、AND, OR, NOT 演算子として、スペース, OR (大文字), - を使用します。

=# SELECT to_tsquery('english', 'Relational Database');
ERROR:  syntax error in tsquery: "Relational Database"

=# SELECT to_tsquery('english', web_query('Relational Database'));
     to_tsquery
---------------------
 'relat' & 'databas'
(1 row)

注意: 現在、OR 演算子よりも AND 演算子のほうが結合順序が高いままです。 一般的なウェブ検索では、OR 演算子のほうが高いものが多いようです。

日本語解析機能

日本語の文字列を扱う関数と、MeCab を直接利用する関数が登録されます。

テキストの正規化 (ja_normalize)

ja_normalize(text) は、入力された日本語テキストを正規化します。 大文字小文字は変換しません。
=# SELECT ja_normalize('カタカナは全角に、ABC123は半角に。ダクテンにも対応。');
                     ja_normalize
------------------------------------------------------
 カタカナは全角に、ABC123は半角に。ダクテンにも対応。
(1 row)

分かち書き (ja_wakachi)

ja_wakachi(text) は、入力された日本語テキストを分かち書きします。 入力の正規化は行いません。
=# SELECT ja_wakachi('分かち書きも使用できます。スペースで区切られます。');
                          ja_wakachi
---------------------------------------------------------------
 分かち書き も 使用 でき ます 。 スペース で 区切ら れ ます 。
(1 row)

mecab による解析 (ja_analyze)

ja_analyze(text) は、入力された日本語テキストを mecab で解析した結果を返します。
=# SELECT * FROM ja_analyze('mecabを利用して形態素解析をします。');
  word  |  type  | subtype1 | subtype2 | subtype3 |  conjtype  | conjugation | basic  |    ruby    | pronounce
--------+--------+----------+----------+----------+------------+-------------+--------+------------+------------
 mecab  | 名詞   | 一般     |          |          |            |             | mecab  | mecab      | mecab
 を     | 助詞   | 格助詞   | 一般     |          |            |             | を     | ヲ         | ヲ
 利用   | 名詞   | サ変接続 |          |          |            |             | 利用   | リヨウ     | リヨー
 し     | 動詞   | 自立     |          |          | サ変・スル | 連用形      | する   | シ         | シ
 て     | 助詞   | 接続助詞 |          |          |            |             | て     | テ         | テ
 形態素 | 名詞   | 一般     |          |          |            |             | 形態素 | ケイタイソ | ケイタイソ
 解析   | 名詞   | サ変接続 |          |          |            |             | 解析   | カイセキ   | カイセキ
 を     | 助詞   | 格助詞   | 一般     |          |            |             | を     | ヲ         | ヲ
 し     | 動詞   | 自立     |          |          | サ変・スル | 連用形      | する   | シ         | シ
 ます   | 助動詞 |          |          |          | 特殊・マス | 基本形      | ます   | マス       | マス
 。     | 記号   | 句点     |          |          |            |             | 。     | 。         | 。
(11 rows)

ふりがな (furigana)

MeCab を利用し、ふりがな(発音)をカタカナで取得します。

=# SELECT furigana('ふりがな(発音)を取得します。');
                furigana
----------------------------------------
 フリガナ(ハツオン)ヲシュトクシマス。
(1 row)

ひらがな変換 (hiragana)

半角/全角カタカナをひらがなへ変換します。

=# SELECT hiragana('ダクテンとゼンカクをひらがなに変換');
              hiragana
------------------------------------
 だくてんとぜんかくをひらがなに変換
(1 row)

カタカナ変換 (katakana)

ひらがなを全角カタカナへ変換します。

=# SELECT katakana('ひらがなを全角カタカナに変換');
           katakana
------------------------------
 ヒラガナヲ全角カタカナニ変換
(1 row)

TODO

mecab のエンコーディングとサーバエンコーディングが異なる場合へ対処する
現在、一致していないと形態素解析の結果が異常になります。
web_query を一般的なウェブサイト互換にする
演算子の優先順位、除外、連語などに対応する必要があります。

Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION

Powered By GForge Collaborative Development Environment