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

xan*_*ngr 17 postgresql full-text-search pattern-matching

我想通过查询得到结果:

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

这有效并返回tsv包含包含的行Available。但是如果我使用avai(dropped lable) 它找不到任何东西。

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

... WHERE content ~* 'letters`
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 29

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

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

没有。因为,除此之外,全文搜索能够进行前缀匹配

这会起作用:

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

注意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:*');
Run Code Online (Sandbox Code Playgroud)
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1
Run Code Online (Sandbox Code Playgroud)

相关答案(请参阅“优化搜索的不同方法”一章):

电子邮件?

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

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

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

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

使用以下命令构建ts_vector列:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;
Run Code Online (Sandbox Code Playgroud)

  • @EvanCarroll:旁白:有史以来*第一次* 认为你错了,这将是第二次。这将是错误的,递归的。;) (5认同)
  • @ErwinBrandstetter,哇,你的方式给了我全速搜索。在你的方式之前,需要`0.380ms`才能获得结果。按照你的方式,它花了`0.079 ms`。 (2认同)