PostgreSQL 使用 nlpbamboo chinesecfg 中文分词
背景
环境 :
CentOS 5.x 64bit
PostgreSQL 9.1.3
nlpbamboo-1.1.2
cmake-2.8.8
CRF++-0.57
安装 :
-- cmake
tar -zxvf cmake-2.8.8.tar.gz
cd cmake-2.8.8
./bootstrap --prefix=/opt/cmake2.8.8
gmake
gmake install
vi ~/.bash_profile
export PATH=/opt/cmake2.8.8/bin:$PATH
. ~/.bash_profile
-- crf
tar -zxvf CRF++-0.57.tar.gz
cd CRF++-0.57
./configure
gmake
gmake install
-- nlpbamboo
vi ~/.bash_profile
export PGHOME=/opt/pgsql
export PATH=$PGHOME/bin:/opt/bamboo/bin:/opt/cmake2.8.8/bin:$PATH:.
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:.
. ~/.bash_profile
tar -jxvf nlpbamboo-1.1.2.tar.bz2
cd nlpbamboo-1.1.2
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=release
gmake all
gmake install
-- 加入lib库链接.
echo "/usr/lib" >>/etc/ld.so.conf (这个命令是bamboo对应的动态链接库)
echo "/usr/local/lib" >>/etc/ld.so.conf (这个命令是CRF对应的动态链接库)
ldconfig -f /etc/ld.so.conf
-- 测试是否加入正常
ldconfig -p|grep bambo
libbamboo.so.2 (libc6,x86-64) => /usr/lib/libbamboo.so.2
libbamboo.so (libc6,x86-64) => /usr/lib/libbamboo.so
ldconfig -p|grep crf
libcrfpp.so.0 (libc6,x86-64) => /usr/local/lib/libcrfpp.so.0
libcrfpp.so (libc6,x86-64) => /usr/local/lib/libcrfpp.so
-- 加入索引
cd /opt/bamboo
wget http://nlpbamboo.googlecode.com/files/index.tar.bz2
tar -jxvf index.tar.bz2
-- 编译PostgreSQL支持模块.
cd /opt/bamboo/exts/postgres/chinese_parser
make
make install
touch $PGHOME/share/tsearch_data/chinese_utf8.stop
cd /opt/bamboo/exts/postgres/pg_tokenize
make
make install
-- 安装PostgreSQL支持模块
su - postgres
cd $PGHOME/share/contrib/
psql -h 127.0.0.1 postgres postgres -f chinese_parser.sql
psql -h 127.0.0.1 postgres postgres -f pg_tokenize.sql
查看全文检索配置中加入了chinesecfg的配置.
postgres=# select * from pg_ts_config;
cfgname | cfgnamespace | cfgowner | cfgparser
------------+--------------+----------+-----------
simple | 11 | 10 | 3722
danish | 11 | 10 | 3722
dutch | 11 | 10 | 3722
english | 11 | 10 | 3722
finnish | 11 | 10 | 3722
french | 11 | 10 | 3722
german | 11 | 10 | 3722
hungarian | 11 | 10 | 3722
italian | 11 | 10 | 3722
norwegian | 11 | 10 | 3722
portuguese | 11 | 10 | 3722
romanian | 11 | 10 | 3722
russian | 11 | 10 | 3722
spanish | 11 | 10 | 3722
swedish | 11 | 10 | 3722
turkish | 11 | 10 | 3722
chinesecfg | 11 | 10 | 33463
(17 rows)
测试tokenize分词函数
postgres=# select * from tokenize('你好我是中国人');
tokenize
---------------------
你好 我 是 中国 人
(1 row)
postgres=# select * from tokenize('中华人民共和国');
tokenize
-----------------
中华人民共和国
(1 row)
postgres=# select * from tokenize('百度');
tokenize
----------
百度
(1 row)
postgres=# select * from tokenize('谷歌');
tokenize
----------
谷歌
(1 row)
postgres=# select * from tokenize('今年是龙年');
tokenize
---------------
今年 是 龙年
(1 row)
测试全文检索类型转换函数
postgres=# select * from to_tsvector('chinesecfg','你好,我是中国人.目前在杭州斯凯做数据库相关的工作.');
to_tsvector
------------------------------------------------------------------------------------------------------------------------------------
-------
',':2 '.':7,17 '中国':5 '人':6 '你好':1 '做':12 '在':9 '工作':16 '我':3 '数据库':13 '斯凯':11 '是':4 '杭州':10 '的':15 '目前':8 '相
关':14
(1 row)
全文检索类型适合场景, 大内容的模糊查询, 非精确的模糊匹配 :
例如, title和content分别保存标题和正文的原始内容, ts_title和ts_content用来保存分词后的全文检索内容.
postgres=# create table blog (id serial primary key, user_id int8, title text, content text, ts_title tsvector, ts_content tsvector);
NOTICE: CREATE TABLE will create implicit sequence "blog_id_seq" for serial column "blog.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "blog_pkey" for table "blog"
CREATE TABLE
在tsvector的字段上可以使用gist索引, 或者gin索引, 加速检索.
postgres=# create index idx_blog_ts1 on blog using gist(ts_title);
CREATE INDEX
postgres=# create index idx_blog_ts2 on blog using gist(ts_content);
CREATE INDEX
插入测试内容 :
postgres=# insert into blog (user_id,title,content,ts_title,ts_content) values (1,'PostgreSQL QQ群 FAQ贴 - 1','QQ群里一些网友问到的 问题,收集如下 :
目录 :
1. PostgreSQL存储过程中自定义异常怎么弄?
2. PostgreSQL9.1的同步事务在某些情况下用户主动cancel等待sync replication standby 的acknowledge,实际本地已提交.
3. PostgreSQL如何满足已经存在则更新, 不存在则插入的需求.
4. copy和insert哪个效率高?
5. PostgreSQL能不能限制数据库的大小?
6. 怎样给一个用户授予只读角色?
7. 不想让数据插入到某个表应该怎么做?
8. PostgreSQL 中有没有rownum这样的,显示结果集的序号?
9. PostgreSQL 函数中如何使用savepoint?
10.请问, pg脚本有宏替换, 计算字符串公式的能力? 类似 a=2 ; evaluate(5-a) ; 如果将这个值赋值给这个变量呢? zresult = evaluate(5-a) ;
11.UPDATE A表 FROM B表 ?
12. hex转decimal
13. PostgreSQL 时区.',to_tsvector('chinesecfg','PostgreSQL QQ群 FAQ贴 - 1'),to_tsvector('chinesecfg','QQ群里一些网友问到的问题,收集如下 :
目录 :
1. PostgreSQL存储过程中自定义异常怎么弄?
2. PostgreSQL9.1的同步事务在某些情况下用户主动cancel等待sync replication standby 的acknowledge,实际本地已提交.
3. PostgreSQL如何满足已经存在则更新, 不存在则插入的需求.
4. copy和insert哪个效率高?
5. PostgreSQL能不能限制数据库的大小?
6. 怎样给一个用户授予只读角色?
7. 不想让数据插入到某个表应该怎么做?
8. PostgreSQL 中有没有rownum这样的,显示结果集的序号?
9. PostgreSQL 函数中如何使用savepoint?
10.请问, pg脚本有宏替换, 计算字符串公式的能力? 类似 a=2 ; evaluate(5-a) ; 如果将这个值赋值给这个变量呢? zresult = evaluate(5-a) ;
11.UPDATE A表 FROM B表 ?
12. hex转decimal
13. PostgreSQL 时区.'));
分词查询测试 :
postgres=# select ts_content from blog;
'(':155,171 ')':157,173 ',':46,60,135,142 '.':28,51,67,189 '1':29 '1.':15 '10.':133 '11.update':175 '12.':182 '13.':186 '2':152 '2.
':26 '3.':52 '4.':68 '5-a':156,172 '5.':76 '6.':86 '7.':96 '8.':109 '9.':125 ':':12,14 ';':153,158,174 '=':151,169 '?':25,75,85,95,1
08,124,132,148,167,181 'a':150,176 'acknowledge':45 'b':179 'cancel':39 'copy':69 'decimal':185 'evaluate':154,170 'from':178 'hex':
183 'insert':71 'pg':136 'postgresql':16,53,77,110,126,187 'postgresql9':27 'qq':1 'replication':42 'rownum':115 'savepoint':131 'st
andby':43 'sync':41 'zresult':168 '一个':89 '一些':3 '下':36 '不':61,79,97 '中':19,111,128 '主动':38 '事务':32 '使用':130 '值赋值':1
62 '做':107 '公式':145 '函数':127 '则':58,63 '到':6,102 '变量':165 '只':92 '同步':31 '呢':166 '和':70 '哪个':72 '在':33 '大小':84 '
下':11 '如何':54,129 '如果':159 '字符串':144 '存储':17 '存在':57,62 '宏替':140 '定义':21 '实际':47 '将':160 '已':49 '已经':56 '序号'
:123 '应该':105 '异常':22 '弄':24 '怎么':23,106 '怎样':87 '情况':35 '想':98 '换':141 '授予':91 '提交':50 '插入':64,101 '收集':10 '效
率':73 '数据':100 '数据库':82 '时区':188 '显示':119 '更新':59 '有':112,114,139 '本':138 '本地':48 '某个':103 '某些':34 '没':113 '满
':55 '用户':37,90 '的':7,30,44,65,83,117,122,146 '目录':13 '等待':40 '类似':149 '结果':120 '给':88,163 '网友':4 '群里':2 '能':78,80
'能力':147 '脚':137 '自':20 '表':104,177,180 '角色':94 '计算':143 '让':99 '请问':134 '读':93 '转':184 '过程':18 '这个':161,164 '这样
':116 '问':5 '问题':8 '限制':81 '集':121 '需求':66 '高':74 ',':9,118
从上面的全文检索类型字段ts_content可以看出, 函数 和 表 在这分词里面, 使用 函数 和 表 作为匹配条件查询时将返回结果, 换个不存在的查询则没有结果 :
postgres=# select user_id,title from blog where ts_content @@ to_tsquery('函数 & 中国');
user_id | title
---------+-------
(0 rows)
postgres=# select user_id,title from blog where ts_content @@ to_tsquery('函数 & 表');
user_id | title
---------+---------------------------
1 | PostgreSQL QQ群 FAQ贴 - 1
(1 row)
查看执行计划 :
postgres=# explain select user_id,title from blog where ts_content @@ to_tsquery('函数 & 中国');
QUERY PLAN
--------------------------------------------------------------------------
Index Scan using idx_blog_ts2 on blog (cost=0.00..4.27 rows=1 width=40)
Index Cond: (ts_content @@ to_tsquery('函数 & 中国'::text))
(2 rows)
postgres=# explain select user_id,title from blog where ts_content @@ to_tsquery('函数 & 表');
QUERY PLAN
--------------------------------------------------------------------------
Index Scan using idx_blog_ts2 on blog (cost=0.00..4.27 rows=1 width=40)
Index Cond: (ts_content @@ to_tsquery('函数 & 表'::text))
(2 rows)
参考
http://code.google.com/p/nlpbamboo/
http://crfpp.googlecode.com/svn/trunk/doc/index.html#download
http://www.cmake.org/
http://www.postgresql.org/docs/9.2/static/datatype-textsearch.html
http://www.postgresql.org/docs/9.2/static/functions-textsearch.html
其他分词工具
1. http://bbs.pgsqldb.com/client/post_show.php?zt_auto_bh=57211
2. http://amutu.com/blog/zhparser/
3. https://github.com/amutu/zhparser