【问题标题】:PostgreSQL full text search randomly dropping lexemesPostgreSQL 全文搜索随机删除词位
【发布时间】:2011-04-29 10:21:01
【问题描述】:

(所有这些都是在 Ubuntu 10.04 上使用 PostgreSQL 9.0.1 完成的,FWIW。)

我已经尝试为 PostgreSQL 编写我自己的词法函数,专门用于名称,基于双变音位算法。为了生成 C lexize 函数,我从 dict_xsyn 示例开始,基本上将双变音位换成了同义词查找。

但可能有 20% 的时间 to_tsvector 被调用,它似乎正在删除词位。例如,我创建了一个包含US Census Bureau's list of names 的表。

db=# select * from names order by rank limit 8;
   name   | freq  | cumfreq | rank 
----------+-------+---------+------
 SMITH    | 1.006 |   1.006 |    1
 JOHNSON  |  0.81 |   1.816 |    2
 WILLIAMS | 0.699 |   2.515 |    3
 JONES    | 0.621 |   3.136 |    4
 BROWN    | 0.621 |   3.757 |    5
 DAVIS    |  0.48 |   4.237 |    6
 MILLER   | 0.424 |    4.66 |    7
 WILSON   | 0.339 |       5 |    8
(8 rows)

然后我们可以添加一个向量列,并用我的变音位字典的to_tsvector 填充它:

db=# alter table names add column vec tsvector;
ALTER TABLE
db=# update names set vec=to_tsvector('public.names', name);
UPDATE 88799
db=# select * from names order by rank limit 8;
   name   | freq  | cumfreq | rank |              vec              
----------+-------+---------+------+-------------------------------
 SMITH    | 1.006 |   1.006 |    1 | 
 JOHNSON  |  0.81 |   1.816 |    2 | 'ANSN':1 'JNSN':1 'johnson':1
 WILLIAMS | 0.699 |   2.515 |    3 | 
 JONES    | 0.621 |   3.136 |    4 | 
 BROWN    | 0.621 |   3.757 |    5 | 
 DAVIS    |  0.48 |   4.237 |    6 | 
 MILLER   | 0.424 |    4.66 |    7 | 'MLR':1 'miller':1
 WILSON   | 0.339 |       5 |    8 | 'ALSN':1 'FLSN':1 'wilson':1
(8 rows)

一堆 vec 字段只是空的!事实上:

db=# select count(1) from names where vec = to_tsvector('');
 count 
-------
 41101
(1 row)

我可以进行批量更新,然后重复计算不匹配的字段,每次都得到不同的计数,因为不同的行无法计算出真正的向量。

但我认为我的 lexize 函数本身还可以吗?

db=# alter table names drop column vec; alter table names add column lexemes varchar[];
ALTER TABLE
ALTER TABLE
db=# update names set lexemes=ts_lexize('dmetaphonedict', name);
UPDATE 88799
db=# select * from names order by rank limit 10;
   name   | freq  | cumfreq | rank |       lexemes        
----------+-------+---------+------+----------------------
 SMITH    | 1.006 |   1.006 |    1 | {smith,SM0,XMT}
 JOHNSON  |  0.81 |   1.816 |    2 | {johnson,JNSN,ANSN}
 WILLIAMS | 0.699 |   2.515 |    3 | {williams,ALMS,FLMS}
 JONES    | 0.621 |   3.136 |    4 | {jones,JNS,ANS}
 BROWN    | 0.621 |   3.757 |    5 | {brown,PRN}
 DAVIS    |  0.48 |   4.237 |    6 | {davis,TFS}
 MILLER   | 0.424 |    4.66 |    7 | {miller,MLR}
 WILSON   | 0.339 |       5 |    8 | {wilson,ALSN,FLSN}
 MOORE    | 0.312 |   5.312 |    9 | {moore,MR}
 TAYLOR   | 0.311 |   5.623 |   10 | {taylor,TLR}
(10 rows)
db=# select count(1) from names where array_length(lexemes,1)=0;
 count 
-------
     0
(1 row)

我可以一遍又一遍地这样做,每次都得到 0 个不匹配。

我正在创建相关的文本搜索字典和配置:

CREATE OR REPLACE FUNCTION ddmetaphonedict_init(internal)
        RETURNS internal
        AS '$libdir/dict_dmetaphone'
        LANGUAGE C STRICT;

CREATE OR REPLACE FUNCTION ddmetaphonedict_lexize(internal, internal, internal, internal)
        RETURNS internal
        AS '$libdir/dict_dmetaphone'
        LANGUAGE C STRICT;

CREATE TEXT SEARCH TEMPLATE dmetaphonedict_template (
        LEXIZE = ddmetaphonedict_lexize,
        INIT   = ddmetaphonedict_init
);

CREATE TEXT SEARCH DICTIONARY dmetaphonedict (
        TEMPLATE = dmetaphonedict_template
);

COMMENT ON TEXT SEARCH DICTIONARY dmetaphonedict IS 'dictionary for names, using dmetaphone';

create text search configuration names (copy=english);
alter text search configuration names alter mapping for asciiword, asciihword, word, hword with dmetaphonedict;

几乎直接来自 dict_xsyn 示例。

发生了什么事?我该怎么做才能弄清楚这些东西被丢弃在哪里?

添加:刚刚在 9.1 中尝试过。 to_tsvector 产生哑 tsvector 的速率大大降低(5 个(只有 5 个,而不是 5k)到 80000+ 个记录中的 7000 个记录)。但它们仍然存在。

【问题讨论】:

  • 我在几年前修复了这个问题,但忘了回来说明如何。而我已经忘记了。 :( 你可以在github.com/jkominek/dmetaphone 看到(工作的)源代码,以防对任何人有帮助。

标签: postgresql full-text-search tsvector


【解决方案1】:

我想首先消除 to_tsvector() 的原因。

我可能首先尝试更改 to_tsvector() 以便它返回一个常量。例如,无论输入参数是什么,都将其更改为返回“'ANSN':1 'JNSN':1 'johnson':1”。 (即使输入参数为 NULL。)如果您的批量更新仍然在“vec”列中留下漏洞,我认为这将清除 to_tsvector()。

我说的对吗?

还考虑一个两步过程,使用 lexize() 填充“lexemes”列,然后使用另一个函数读取词位并在“vec”列中生成值。

【讨论】:

    猜你喜欢
    • 2018-12-07
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多