在全文检索中,词频统计是一个比较常见的需求。例如我们需要分析两个文本的相似性时使用的TF(Term Frequency 词频)/IDF(Inverse Document Frequency 逆向文本频率)算法就需要统计词频。
那么pg中如何在一堆文本中,找到热词,或者对词频进行分析呢?
pg内置的ts_stat函数可以实现该功能,ts_stat函数用法如下:
ts_stat(sqlquery text, [ weights text, ]
OUT word text, OUT ndoc integer,
OUT nentry integer) returns setof record
其中的几个参数分别是:
Sqlquery:是包含SQL查询的文本值,该查询必须返回单个tsvector列。
word text:词的值。
ndoc integer:单词出现的文档数。
nentry integer:单词出现的总数。
例子:
1、创建生成随机字符串的函数
bill=# create or replace function gen_rand_str(int) returns text as $$
bill$# select substring(md5(random()::text), 4, $1);
bill$# $$ language sql strict stable;
CREATE FUNCTION
2、创建生成若干个随机词的函数
bill=# create or replace function gen_rand_tsvector(int,int) returns tsvector as $$
bill$# select array_to_tsvector(array_agg(gen_rand_str($1))) from generate_series(1,$2);
bill$# $$ language sql strict;
CREATE FUNCTION
3、创建测试表,并写入测试数据
bill=# create table ts_test(id int, info tsvector);
CREATE TABLE
bill=# insert into ts_test select generate_series(1,100000), gen_rand_tsvector(4,10);
INSERT 0 100000
4、查看词频,总共出现了多少次,在多少篇文本(多少条记录中出现过)
bill=# SELECT * FROM ts_stat('SELECT info FROM ts_test')
bill-# ORDER BY nentry DESC, ndoc DESC, word
bill-# LIMIT 10;
word | ndoc | nentry
------+------+--------
4b1c | 35 | 35
5a11 | 35 | 35
a181 | 34 | 34
f6a2 | 34 | 34
26f2 | 32 | 32
4f3b | 32 | 32
d561 | 32 | 32
0d4c | 31 | 31
126e | 31 | 31
22f5 | 31 | 31
(10 rows)
5、再写入一批测试数据,查看词频,总共出现了多少次,在多少篇文本(多少条记录中出现过)
bill=# insert into ts_test select generate_series(1,100000), gen_rand_tsvector(2,10);
INSERT 0 100000
bill=# SELECT * FROM ts_stat('SELECT info FROM ts_test')
bill-# ORDER BY nentry DESC, ndoc DESC, word
bill-# LIMIT 10;
word | ndoc | nentry
------+------+--------
ae | 4051 | 4051
c0 | 4010 | 4010
e2 | 4009 | 4009
d9 | 3967 | 3967
6a | 3964 | 3964
19 | 3956 | 3956
bb | 3955 | 3955
f7 | 3951 | 3951
15 | 3937 | 3937
dd | 3935 | 3935
(10 rows)