its*_*e69 9 postgresql full-text-search pattern-matching tsvector
我正在寻找一种方法来模拟SELECT * FROM table WHERE attr LIKE '%text%'
在PostgreSQL中使用tsvector之类的东西.
我没有使用字典就创建了一个tsvector属性.现在,像...这样的查询
SELECT title
FROM table
WHERE title_tsv @@ plainto_tsquery('ph:*');
Run Code Online (Sandbox Code Playgroud)
...将返回所有标题,如'Physics','PHP'等.但是,如何创建一个返回所有标题的查询,其中标题以'Zend Fram'开头(应该返回例如'Zend Framework')?
当然,我可以使用类似的东西:
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend')
AND title_tsv @@ to_tsquery('fram:*');
Run Code Online (Sandbox Code Playgroud)
然而,这似乎有点尴尬.
所以,问题是:有没有办法用以下方法制定上面给出的查询:
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend fram:*');
Run Code Online (Sandbox Code Playgroud)
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend') and
title_tsv @@ to_tsquery('fram:*')
Run Code Online (Sandbox Code Playgroud)
相当于:
SELECT title
FROM table
WHERE title_tsv @@ to_tsquery('zend & fram:*')
Run Code Online (Sandbox Code Playgroud)
但当然发现"Zend也没有框架".
当然,你可以在tsquery匹配之后表达与标题的正则表达式匹配,但你必须使用explain analyze来确保在tsquery之后而不是之前执行.
不是一个很好的解决方案,但它应该可以完成这项工作:
psql=# SELECT regexp_replace(cast(plainto_tsquery('Zend Fram') as text), E'(\'\\w+\')', E'\\1:*', 'g') ;
regexp_replace
---------------------
'zend':* & 'fram':*
(1 row)
Run Code Online (Sandbox Code Playgroud)
它可以像这样使用:
psql=# SELECT title FROM table WHERE title_tsv(title) @@ to_tsquery(regexp_replace(cast(plainto_tsquery('Zend Fram') as text), E'(\'\\w+\')', E'\\1:*', 'g'));
Run Code Online (Sandbox Code Playgroud)
这是如何工作的:
cast(plainto_tsquery('Zend Fram') as text)
:*
前缀匹配器附加到每个搜索词:regexp_replace(..., E'(\'\\w+\')', E'\\1:*', 'g')
to_tsquery(...)
SELECT title FROM table WHERE title_tsv(title) @@ ...
Postgres 9.6引入了用于全文搜索的短语搜索功能。所以这现在工作:
SELECT title
FROM tbl
WHERE title_tsv @@ to_tsquery('zend <-> fram:*');
Run Code Online (Sandbox Code Playgroud)
它找到“ foo Zend framework bar”或“ Zendframes”,但找不到 “ foo Zend has no framework bar”。
可以使用新的运算符
<->
和在tsquery输入中指定词组搜索查询。前者表示词素之前和之后的词素必须按该顺序彼此相邻出现。后者意味着它们必须完全分开词素。<
N
>
N
为了获得最佳性能支持,请使用GIN索引查询:
CREATE INDEX tbl_title_tsv_idx ON tbl USING GIN (title_tsv);
Run Code Online (Sandbox Code Playgroud)
或者根本不存储title_tsv
在表中(使表膨胀和使写入复杂化)。您可以改用表达式索引:
CREATE INDEX tbl_title_tsv_idx ON tbl USING GIN (to_tsvector('english', title));
Run Code Online (Sandbox Code Playgroud)
您需要指定文本搜索配置(通常是特定于语言的)以使表达式不可变。并相应地调整查询:
...
WHERE to_tsvector('english', title) @@ to_tsquery('english', 'zend <-> fram:*');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10482 次 |
最近记录: |