Ant*_*ner 17 sql postgresql full-text-search
在这里发布一个关于如何提高我的SQL搜索方法速度的问题后,我被建议更新我的表以使用全文搜索.这就是我现在所做的,使用Gist索引来加快搜索速度.在一些"普通"查询中,我注意到了一个显着的增长,我很高兴.
但是,我在搜索部分单词时遇到了困难.例如,我有几个包含单词Squire(454)的记录,我有几个包含Squirrel(173)的记录.现在,如果我搜索Squire它只返回454条记录,但我也希望它返回Squirrel记录.
我的查询看起来像这样
SELECT title
FROM movies
WHERE vectors @@ to_tsoquery('squire');
Run Code Online (Sandbox Code Playgroud)
我以为我能做到,to_tsquery('squire%')但那不起作用.
如何让它搜索部分匹配?
此外,在我的数据库中,我有电影和其他只是电视节目的记录.这些在名称上区别于"",因此"Munsters"是电视节目,而Munsters则是电影节目.我希望能够做的只是搜索电视节目和电影.有关如何实现这一点的任何想法?
关心Anthoni
小智 52
尝试,
SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire:*')
Run Code Online (Sandbox Code Playgroud)
这适用于PostgreSQL 8.4+
Jos*_*rns 31
Anthoni,
假设您计划仅使用ASCII编码(可能很难,我知道),一个非常可行的选项可能是Trigram(pg_trgm)模块:http://www.postgresql.org/docs/9.0/interactive/pgtrgm. HTML
Trigram使用内置的索引方法,如Gist和Gin.您必须进行的唯一修改是在定义索引时,指定任一gist_trgm_ops或的运算符类gin_trgm_ops.
如果尚未安装contrib模块,那么在Ubuntu中就可以轻松地从shell运行以下命令:
# sudo apt-get install postgresql-contrib
Run Code Online (Sandbox Code Playgroud)
使contrib模块可用后,必须将pg_trgm扩展安装到相关数据库中.您可以通过在要将模块安装到的数据库上执行以下PostgreSQL查询来执行此操作:
CREATE EXTENSION pg_trgm;
Run Code Online (Sandbox Code Playgroud)
安装pg_trgm扩展后,我们已经准备好了!
-- Create a test table.
CREATE TABLE test (my_column text)
-- Create a Trigram index.
CREATE INDEX test_my_colun_trgm_idx ON test USING gist (my_column gist_trgm_ops);
-- Add a couple records
INSERT INTO test (my_Column) VALUES ('First Entry'), ('Second Entry'), ('Third Entry')
-- Query using our new index --
SELECT my_column, similarity(my_column, 'Frist Entry') AS similarity FROM test WHERE my_column % 'Frist Entry' ORDER BY similarity DESC
Run Code Online (Sandbox Code Playgroud)
@ alexander-mera解决方案效果很好!
注意:还要确保将空格转换为+.例如,如果您正在搜索squire knight.
SELECT title FROM movies WHERE to_tsvector(title) @@ to_tsquery('squire+knight:*')
Run Code Online (Sandbox Code Playgroud)
即使使用LIKE你也无法获得'松鼠',squire%因为'松鼠'有两个'r'.要获得Squire和Squirrel,您可以运行以下查询:
SELECT title FROM movies WHERE vectors @@ to_tsquery('squire|squirrel');
Run Code Online (Sandbox Code Playgroud)
要区分电影和电视节目,您应该在数据库中添加一列.然而,有很多方法可以给这只猫皮肤.您可以使用子查询强制postgres首先找到匹配'squire'和'squirrel'的电影,然后搜索该子集以查找以'''开头的标题.可以创建用于LIKE '"%...'搜索的索引.
如果没有探索其他索引的可能性,你也可以运行它们 - 搞乱它们以找到最快的:
SELECT title
FROM (
SELECT *
FROM movies
WHERE vectors @@ to_tsquery('squire|squirrel')
) t
WHERE title ILIKE '"%';
Run Code Online (Sandbox Code Playgroud)
要么
SELECT title
FROM movies
WHERE vectors @@ to_tsquery('squire|squirrel')
AND title ILIKE '"%';
Run Code Online (Sandbox Code Playgroud)
对此的广泛解决方案是使用 PG 的 ts_rewrite 函数来设置适用于替代匹配的别名表(请参阅查询重写)。这涵盖了像上面这样的情况,同时还处理完全不同的情况,例如搜索tree rat和获取结果squirrel等。
该链接的完整详细信息和解释,但其要点是您可以设置一个带有 2 个 ts_query 列的别名表,并将该表的查询传递到您的搜索中,如下所示:
CREATE TABLE aliases (t tsquery primary key, s tsquery);
INSERT INTO aliases VALUES(to_tsquery('supernovae'), to_tsquery('supernovae|sn'));
SELECT ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases');
Run Code Online (Sandbox Code Playgroud)
导致最终查询看起来更像:
WHERE vectors @@ ts_rewrite(to_tsquery('supernovae & crab'), 'SELECT * FROM aliases')
Run Code Online (Sandbox Code Playgroud)
这类似于 PG 中的同义词设置,但每次添加内容时都不需要完全重新索引。当您遇到很少的拼写变化和“当我搜索这个时,我希望得到这样的结果”的情况时,很容易将它们快速添加到表格中。您可以向该表添加更多列,并且只要基于查询ts_rewrite返回 2 个预期to_tsquery列。
当您深入研究该文档时,您还会看到建议的性能调整示例。在使用trigram 来提高速度和使用vector/query/rewrite 来提高健壮性之间有一个平衡。
| 归档时间: |
|
| 查看次数: |
26036 次 |
| 最近记录: |