在postgresql中使用to_tsvector和to_tsquery处理拼写错误

时间:2018-05-15 07:10:33

标签: sql postgresql pg

我有一个包含这些字段enter image description here

的简单表格

最后两个字段用于使用tsvector数据类型索引一个字段,使用text数据类型索引其他字段。

我想对name或id执行查询。我这样做

SELECT * FROM foo WHERE foo.searchtext @@ to_tsquery('1234 & abcd');  

它工作正常,但现在我想删除拼写错误,例如,如果名称是abcd我键入abbd然后它应该获得所有可能的值。 我见过pg_tgrm(),但does not使用整数或tsvector

我尝试使用其他选项pg_tgrm()就像我已将索引存储在另一个字段searchtextstring中,类型为text和query

select *
      from foo
    where searchtextstring % '123' and searchtextstring % 'abbd';

但我不认为这是有效的,这也不适用于拼写错误。

那么如何使用to_tsquery来处理拼写错误?

由于

1 个答案:

答案 0 :(得分:2)

全文搜索仅忽略词干和大小写的差异,它不允许您根据相似性找到匹配项。

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)

这不是因为“它不起作用”,而是因为这些词语不够相似。不要忘记四个字母的单词中没有那么多的三字母,所以如果你换一个字母,它们就不再那么相似了。这并不奇怪,对吧?

所以我们必须降低相似性阈值才能得到结果;

SET pg_trgm.similarity_threshold = 0.1;

SELECT * FROM foo WHERE searchtextstring % '1234'
                    AND searchtextstring % 'abcd';

 id | searchtextstring 
----+------------------
  2 | abbd 1224
(1 row)