2010-10-22 51 views
2

(所有這一切都是在PostgreSQL 9.0.1在Ubuntu 10.04,FWIW完成。)PostgreSQL的全文檢索隨機丟棄詞素

我試着寫我自己的lexize功能的PostgreSQL專門爲名稱的基礎上,雙metaphone算法。爲了生成C lexize函數,我開始使用dict_xsyn示例,並基本上將雙元metaphone交換爲同義詞查找。

但也許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條記錄)。但他們仍然在那裏。

回答

1

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

我可能會首先嚐試更改to_tsvector(),以便它返回一個常量。例如,將其更改爲返回「'ANSN':1'JNSN':1'johnson':1」,不管它的輸入參數是什麼。 (即使輸入參數爲NULL。)如果你的批量更新仍然留下「vec」列,我認爲這將清除to_tsvector()。

我說得對嗎?

另外考慮兩個步驟的過程,使用lexize()來填充列「詞位」,然後讀取詞位並生成列「vec」中的值的另一個函數。