2010-10-22 2 views
2

(Все это было сделано с PostgreSQL 9.0.1 на Ubuntu 10.04, FWIW.)PostgreSQL полнотекстового поиска случайно сбросив лексемы

Я пытался писать свою собственную функцию lexize для 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 моего Metaphone словаря:

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 примера.

Что происходит? Что я могу сделать, чтобы выяснить, где эти вещи отбрасываются?

ADDED: Просто попробовал это с 9.1. Скорость, с которой to_tsvector создает dud tsvector, значительно уменьшается (5 (всего 5, не 5k) до 7000 записей из 80000+). Но они все еще там.

ответ

1

Я хотел бы сначала исключить to_tsvector() в качестве причины.

Я мог бы сначала попробовать изменить to_tsvector(), чтобы он возвращал константу. Например, измените его, чтобы вернуть «ANSN»: 1 'JNSN': 1 'johnson': 1 "независимо от его входных аргументов. (Даже если входные аргументы NULL.) Если ваше массовое обновление все еще оставляет дыры в столбце «vec», я думаю, что это очистит to_tsvector().

Я прав, что?

Также рассмотрим двухэтапный процесс, используя lexize() для заполнения столбца «lexemes», затем другую функцию для чтения лексем и получения значений в столбце «vec».

Смежные вопросы