从GIN索引的TSVECTOR列获取部分匹配


13

我想通过查询获得结果:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

这可以正常工作并返回tsv包含的行Available。但是,如果我使用avai(放置lable),它什么也找不到。

所有查询都必须在字典中吗?我们不能只查询这些字母吗?我有一个包含电子邮件正文(内容)的数据库,我希望它随着每秒的增长而快速发展。目前我正在使用

... WHERE content ~* 'letters`

Answers:


22

所有查询都必须在字典中吗?

否。因为只有词干(根据使用的文本搜索配置)才在索引中开头。但更重要的是:

没有。因为,除了全文搜索之外,还可以进行前缀匹配

这将工作:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

注意3件事:

  1. 在这种情况下,请使用to_tsquery(),而不是plainto_tsquery(),因为(引用手册):

    ... plainto_tsquery将无法tsquery在其输入中识别运算符,权重标签或前缀匹配标签

  2. 使用'simple'文本搜索配置生成,tsquery因为您显然想直接使用“ avail”一词,而不应用词干。

  3. 附加:*使其成为前缀搜索,即查找所有以“ avail”开头的词素。

重要提示:这是对文档中词素(词干)的前缀搜索。没有通配符(content ~* 'avail')的正则表达式匹配不完全相同!后者不是左锚定的(到词首开始),还会找到“ FOOavail”等。

目前尚不清楚是要查询中概述的行为还是要添加的正则表达式的等效行为。pg_trgm@Evan这样已经建议过的Trigram索引()是正确的工具。dba.SE上有许多相关问题,请尝试搜索

概述:

演示版

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

最近的相关答案(优化搜索的不同方法):

电子邮件?

由于您提到了电子邮件,因此请注意,文本搜索解析器可识别电子邮件,并且不会将其拆分为单独的单词/词素。考虑:

SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

我会用空格()替换分隔符@.在您的电子邮件中' '为包含的单词建立索引。

另外,由于您处理的是电子邮件中的名称,而不是英语(或其他某种语言)的单词,因此我将使用'simple'文本搜索配置来禁用词干和其他语言功能:

使用以下方法构建ts_vector列:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

我将为此删除我的答案,因为无论哪种方式,都是因为我第一次有明显的错误,所以我不想被人提醒。我有两个问题供您参考:1)记录在何处:*; 2)不应提一下构建to_tsvector('simple'..)指令的指示,以便将来查询该tsv时也需要tsquery的“简单”配置?我认为您应该澄清在tsvector / tsquery上禁用词干的后果。
埃文·卡罗尔

@EvanCarroll:使用“简单”的配置不是必需的。它只是避免了可能会或可能不会出现的词干(例如“鼠”到“鼠”)。对于给定的示例不理想。手册:我已经在上方添加了链接...
Erwin Brandstetter,2013年

4
@EvanCarroll:另外:一次认为你错了,那将是第二次。这将是错误的,递归地。;)
Erwin Brandstetter

2
@ErwinBrandstetter,哇,您的方式为我提供了全速搜索。在您0.380ms采取行动之前,必须先取得成果。按照你的方式去0.079 ms
xangr

1
@xangr:否,FTS仅提供词素的前缀匹配。有关更多信息,请参见pg_trgm。FTS更快(索引更小)。您甚至可以合并两个索引...
Erwin Brandstetter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.