Полнотекстовый поиск игнорирует только различия в основаниях и заглавных буквах, он не позволит вам найти совпадения по сходству.
pg_trgm
- это путь.
Я использую этот образец таблицы:
CREATE TABLE foo (id integer PRIMARY KEY, searchtextstring text);
INSERT INTO foo VALUES (1, 'something 0987');
INSERT INTO foo VALUES (2, 'abbd 1224');
CREATE INDEX ON foo USING gist (searchtextstring gist_trgm_ops);
Это настолько мало, что PostgreSQL всегда будет использовать последовательное сканирование, поэтому давайте по возможности заставим PostgreSQL использовать индекс (чтобы мы могли смоделировать таблицу большего размера):
SET enable_seqscan = off;
Теперь давайте запрос:
EXPLAIN (COSTS off)
SELECT * FROM foo WHERE searchtextstring % '1234'
AND searchtextstring % 'abcd';
QUERY PLAN
--------------------------------------------------------
Index Scan using foo_searchtextstring_idx on foo
Index Cond: ((searchtextstring % '1234'::text)
AND (searchtextstring % 'abcd'::text))
(2 rows)
Индекс используется довольно хорошо, при одном сканировании индекса!
Но запрос не возвращает строк:
SELECT * FROM foo WHERE searchtextstring % '1234'
AND searchtextstring % 'abcd';
id | searchtextstring
----+------------------
(0 rows)
Это не потому, что & ldquo; он не работает & rdquo;, а потому, что слова недостаточно похожи. Не забывайте, что в четырехбуквенном слове не так много триграмм, поэтому, если вы измените одну букву, они уже не будут такими похожими. Это не удивительно, правда?
Таким образом, мы должны снизить порог подобия, чтобы получить результат;
SET pg_trgm.similarity_threshold = 0.1;
SELECT * FROM foo WHERE searchtextstring % '1234'
AND searchtextstring % 'abcd';
id | searchtextstring
----+------------------
2 | abbd 1224
(1 row)