一段时间以来,我一直在玩弄全文的想法,尽管我已经完成了所有的阅读和实验,但我仍然觉得我有很多东西要了解它的优点/缺点和一般实用性。
对于很多事情来说,它似乎工作得非常好,但是我最近遇到的一个主要障碍是在涉及真实的人名时 - 简单地说,它在涉及撇号、特殊字符、重音和类似。所以我硬着头皮决定尝试编写自己的触发函数来更新我希望索引的“搜索”字段。
首先,当搜索像 Bjorn 这样的名字时,问题就出现了,当你也可以有一个 Bjørn 或 Björn 时,那么 - 或者 O'Leary 怎么样,全文将这个词分成两部分。如果有人键入没有撇号的名称怎么办?等等。
为了解决这个问题,我目前的努力如下:
CREATE OR REPLACE FUNCTION quote_insert() RETURNS TRIGGER AS $$
DECLARE
--Set to lowercase and convert any strange vowels or accents to ascii (no Bjørn's, José's etc)
myString text := to_ascii(convert_to(lower(NEW."name"),'latin1'),'latin1');
nwString text := '';
--Split the words up by their spaces and put them in an array
myArray text[] := regexp_split_to_array(myString, E'\\s+');
nArray text[];
--These are counters for the secondary array, and for the apostrophe placement
n int := 0;
p int;
BEGIN
FOR i IN 1..array_upper(myArray,1) LOOP
--If it has an apostrophe (hopefully only one!) split the words up like so: o'leary -> oleary o leary
IF position('''' in myArray[i]) > 0
THEN
nArray[n] = '''' || regexp_replace(myArray[i], '''', '') || ''':' || n+1 || ' ';
n = n+1;
p = position('''' in myArray[i]);
nArray[n] = '''' || substring(myArray[i],0,p) || ''':' || n+1 || ' ';
n = n+1;
nArray[n] = '''' || substring(myArray[i],p+1,length(myArray[i])) || ''':' || n+1 || ' ';
n = n+1;
ELSE
nArray[n] = '''' || myArray[i] || ''':' || n+1 || ' ';
n = n+1;
END IF;
END LOOP;
--Sort 'nArray' here..........
--(not even sure if sorting alphabetically is important...)
--............................
--Turn the array back into a string
FOR i IN 0..array_upper(nArray,1) LOOP
nwString = nwString || nArray[i];
END LOOP;
--Set the search field to whatever string is generated
NEW."search" = trim(nwString);
RETURN NEW;
END
$$ LANGUAGE 'plpgsql';
我差点忘了,我之前添加了一个非常方便的自定义 to_ascii 脚本,这是我从另一个站点提取的 -
CREATE FUNCTION to_ascii(bytea, name)
RETURNS text STRICT AS 'to_ascii_encname' LANGUAGE internal;
因此,我的脚本触发器生成的文本类似于全文,唯一的区别是我注意到它按字母顺序排列单词。我不知道是否有必要,或者这样做是否有效,但如果我必须这样做,那么欢迎提出关于排序的建议。
要比较此脚本的结果和全文,它将读取:
My query (firing trigger function):
INSERT INTO "table" ("name") VALUES ('Bjørn O''Leary') RETURNING "search";
[search]
'bjorn':1 'oleary':2 'o':3 'leary':4
Using fulltext:
SELECT to_tsvector('Bjørn & O''Leary & OLeary'); --Obviously using o'leary and oleary because of different sorting methods
[to_tsvector]
'bjørn':1 'leari':3 'o':2 'oleari':4
如您所见,它并没有删除特殊的 ø 字符,显然我需要插入 OLeary 以获得类似的结果。
所以,要问问题:按字母顺序组织单词是否更好/必要/更快?
其次......我现在不想问这个问题,但是已经有一种全文方法来查询符合我的标准的名称,我只是不知道吗?
最后,真正令人头疼的是,我的名字分布在从单个表继承的多个表中。我可能会考虑向这个触发器添加一个插入/更新,以更新一个完全独立的“搜索”表。这是不是太过分了?