読者です 読者をやめる 読者になる 読者になる

脳みそスワップアウト

揮発性なもので。おもにPHPのこととか。

PostgreSQLで全文検索

PostgreSQL textsearch_ja

PostgreSQL形態素解析全文検索をするなら textsearch_ja を使う模様。
GIN indexのmecabでの実装。

お仕事で使ったので,構築手順と動作確認のメモ書き。
CentOS-5.5 x86_64。


Postgresの全文検索のところのドキュメントは読んでおく必要がある。
http://www.postgresql.jp/document/pg915doc/html/textsearch.html
textsearch_jaの公式はこれ。
http://textsearch-ja.projects.postgresql.org/textsearch_ja.html




mecab-0.994 のビルド

#!/bin/bash

./configure --prefix=/home/pen/local/mecab-0.994 \
--enable-utf8-only

make && ~/local/bin/paco -lD+ make install

mecab-ipadic-2.7.0-20070801 のビルド

#!/bin/bash

MECAB_HOME=/home/pen/local/mecab-0.994

./configure \
--with-mecab-config=${MECAB_HOME}/bin/mecab-config \
--with-charset=utf8

make && ~/local/bin/paco -lD+ make install

postgresql-9.1.6 のビルド

#!/bin/bash

PG_HOME=/usr/local/postgres-9.1.6
DATA_DIR=${PG_HOME}/data

./configure --prefix=${PG_HOME}

make && sudo /home/pen/local/bin/paco -lD+ make install

sudo mkdir -p ${DATA_DIR}
sudo chown postgres:postgres ${DATA_DIR}

postgres初期化

#!/bin/bash

LOGFILE=/home/postgres/var/log/postgres.log
DATA_DIR=${PG_HOME}/data

mkdir -p ${DATA_DIR}

${PG_HOME}/bin/initdb -E UTF-8 -D ${DATA_DIR}

postgres起動

#!/bin/bash

LOGFILE=/home/postgres/var/log/postgres.log
DATA_DIR=${PG_HOME}/data

MECAB_HOME=/home/pen/local/mecab-0.994
export LD_LIBRARY_PATH=${MECAB_HOME}/lib

${PG_HOME}/bin/pg_ctl -D ${DATA_DIR} -l ${LOGFILE} start

tail ${LOGFILE}

ユーザ&DB作成

#!/bin/bash

LOGFILE=/home/pen/var/log/postgres.log
DATA_DIR=${PG_HOME}/data


${PG_HOME}/bin/createuser -e pen
${PG_HOME}/bin/createdb -e -E UTF-8 -O pen hoge


textsearch_ja-9.0.0 のビルド。
BOM付きのUTF-8なので,古めのgccだとビルドできないから頭3バイトを削っている。

#!/bin/bash

PG_HOME=/usr/local/postgres-9.1.6
MECAB_HOME=/home/pen/local/mecab-0.994

DBUSER=pen
DBNAME=hoge
DBHOST=localhost
DBPORT=5432

export PATH=${PATH}:${PG_HOME}/bin
export LD_LIBRARY_PATH=${MECAB_HOME}/lib

make clean

# remove BOM
`ls textsearch_ja.c.org >/dev/null 2>&1`
if [ $? != 0 ]; then
    cp -p textsearch_ja.c textsearch_ja.c.org
    tail -c +4 textsearch_ja.c.org > textsearch_ja.c
fi
`ls encoding_eucjp.c.org >/dev/null 2>&1`
if [ $? != 0 ]; then
    cp -p encoding_eucjp.c encoding_eucjp.c.org
    tail -c +4 encoding_eucjp.c.org > encoding_eucjp.c
fi
`ls encoding_utf8.c.org >/dev/null 2>&1`
if [ $? != 0 ]; then
    cp -p encoding_utf8.c encoding_utf8.c.org
    tail -c +4 encoding_utf8.c.org > encoding_utf8.c
fi


make CFLAGS=-I${MECAB_HOME}/include LDFLAGS=-L${MECAB_HOME}/lib
sudo PATH=${PATH} /home/pen/local/bin/paco -lD make install

${PG_HOME}/bin/psql -e -f ${PG_HOME}/share/contrib/textsearch_ja.sql -U ${DBUSER} -h ${DBHOST} -p ${DBPORT} ${DBNAME}
sudo cp dict/japanese.syn ${PG_HOME}/share/tsearch_data 

# Install japanese synonym dictionary
SQL=`cat << EOF
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;
EOF
`

echo $SQL | ${PG_HOME}/bin/psql -e -f - -U ${DBUSER} -h ${DBHOST} -p ${DBPORT} ${DBNAME}

psql起動

${PG_HOME}/bin/psql -U pen hoge

類義語辞書が使われる設定になっていることを確認

hoge=# \dF+ japanese
Text search configuration "pg_catalog.japanese"
Parser: "pg_catalog.japanese"
      Token      |    Dictionaries
-----------------+---------------------
 asciihword      | english_stem
 asciiword       | english_stem
 email           | simple
 file            | simple
 float           | simple
 host            | simple
 hword           | japanese_syn,simple
 hword_asciipart | english_stem
 hword_numpart   | simple
 hword_part      | japanese_syn,simple
 int             | simple
 numhword        | simple
 numword         | simple
 sfloat          | simple
 uint            | simple
 url             | simple
 url_path        | simple
 version         | simple
 word            | japanese_syn,simple

形態素解析がされることを確認

hoge=# SELECT to_tsquery('japanese', '形態素解析がされます');
               to_tsquery
----------------------------------------
 '形態素' & '解析' & 'さ' & 'れ'
(1 row)

類義語(Synonim)の確認。
${PG_HOME}/share/tsearch_data/japanese.syn に以下を追加して

マクドナルド    マック
マクド  マック
マッキントッシュ    マック

Synonym辞書再読み込み

hoge=# ALTER TEXT SEARCH DICTIONARY japanese_syn(dummy);

抽出とハイライト。

hoge=# SELECT to_tsvector('japanese', 'マックでのんびりマッキントッシュ') @@ to_tsquery('japanese', 'マッキントッシュ');
 ?column?
----------
 t
(1 row)

hoge=# SELECT ts_headline('japanese', 'マックでのんびりマッキントッシュ', to_tsquery('japanese', 'マッキントッシュ'));
                          ts_headline
----------------------------------------------------------------
 <b>マック</b>でのんびり<b>マッキントッシュ</b>
(1 row)


Synonym辞書のフォーマットは,左も右も形態素
形態素 to 形態素 のSynonym。

左側は重複NGだけど,もしした場合は後から定義したものが勝つ模様。