私はここしばらくフルテキストのアイデアをいじっていましたが、読んだり実験したりしたにもかかわらず、その利点/欠点や一般的な実用性について学ぶべきことがまだたくさんあると感じています.
多くの場合、それは非常にうまく機能しているように見えますが、最近私が抱えている大きな問題は、実在の人物の名前に関してです。簡単に言えば、アポストロフィ、特殊文字、アクセント、およびなど。そこで私は弾丸を噛み、インデックスを作成したい「検索」フィールドを更新する独自のトリガー関数を作成してみることにしました。
まず、Bjorn のような名前を検索するときに問題が発生します。Bjørn または Björn を使用することもできますが、O'Leary については、フルテキストで単語が 2 つの部分に分割されます。誰かがアポストロフィなしで名前を入力したらどうなりますか? 等々。
それに対処するために、私の現在の取り組みは次のとおりです。
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 を挿入する必要がありました。
では、質問をしてみましょう: 単語をアルファベット順に整理する方が良い/必要/速いですか?
第二に...私は今これを尋ねるのは嫌いですが、私が気付いていない私の基準に従う名前を照会するフルテキストの方法はすでにありますか?
最後に、本当の頭痛の種は、単一のテーブルから継承された複数のテーブルにまたがる名前があることです。完全に別個の「検索」テーブルを更新するために、このトリガーに挿入/更新を追加することを検討する場合があります。これは行き過ぎですか?