3

我想知道是否可以创建一个 Postgres 函数来扫描一些表行并创建一个包含WORDAMOUNT(频率)的表?我的目标是使用这个表来创建一个词云。

4

2 回答 2

5

有一种简单的方法,但它可能会很慢(取决于您的桌子大小)。您可以将文本拆分为数组:

SELECT string_to_array(lower(words), ' ') FROM table;

使用这些数组,您可以使用unnest它们来聚合它们:

WITH words AS (
    SELECT unnest(string_to_array(lower(words), ' ')) AS word
    FROM table
)
SELECT word, count(*) FROM words
GROUP BY word;

这是一种简单的方法,但存在一些问题,例如,它只用空格而不是标点符号来分割单词。

其他可能更好的选择是使用PostgreSQL 全文搜索

于 2013-02-19T12:57:34.433 回答
4

聚会迟到了,但我也需要这个,并想使用全文搜索。
可以方便地删除 html 标签。

所以基本上你将文本转换为 atsvector然后使用ts_stat

select word, nentry 
from ts_stat($q$ 
    select to_tsvector('simple', '<div id="main">a b c <b>b c</b></div>') 
$q$)
order by nentry desc

结果:

|word|nentry|
|----|------|
|c   |2     |
|b   |2     |
|a   |1     |

但这不能很好地扩展,所以这就是我的想法:

设置:

-- table with a gist index on the tsvector column
create table wordcloud_data (
    html text not null,
    tsv tsvector not null
);
create index on wordcloud_data using gist (tsv);

-- trigger to update the tsvector column
create trigger wordcloud_data_tsvupdate 
    before insert or update on wordcloud_data 
    for each row execute function tsvector_update_trigger(tsv, 'pg_catalog.simple', html);

-- a view for the wordcloud
create view wordcloud as select word, nentry from ts_stat('select tsv from wordcloud_data') order by nentry desc;

用法:

-- insert some data
insert into wordcloud_data (html) values 
    ('<div id="id1">aaa</div> <b>bbb</b> <i attribute="ignored">ccc</i>'), 
    ('<div class="class1"><span>bbb</span> <strong>ccc</strong> <pre>ddd</pre></div>');

之后,您的wordcloud视图应如下所示:

|word|nentry|
|----|------|
|ccc |2     |
|bbb |2     |
|ddd |1     |
|aaa |1     |

额外功能:
替换simple为例如english,postgres 将删除停用词并为您进行词干提取。

于 2020-06-17T21:07:52.733 回答