将源自不同表的两个 postgresql tsvector 字段连接到单个 postgresql 视图中,以启用联合全文搜索

Posted

技术标签:

【中文标题】将源自不同表的两个 postgresql tsvector 字段连接到单个 postgresql 视图中,以启用联合全文搜索【英文标题】:Concat two postgresql tsvector fields originating in separate tables into single postgresql view to enable joined full text search 【发布时间】:2014-05-03 14:36:51 【问题描述】:

我有一个由 3 个表组合而成的 postgresql 视图:

create view search_view as 
select u.first_name, u.last_name, a.notes, a.summary, a.search_index 
from user as u, assessor as a, connector as c 
where a.connector_id = c.id and c.user_id = u.id;

但是,我需要将 3 个表中的 2 个表中的 tsvector 字段连接到视图中的单个 tsvector 字段中,该字段提供跨 4 个字段的全文搜索:2 个来自一个表,2 个来自另一个。

我已阅读文档,说明我可以使用 concat 运算符来组合两个 tsvector 字段,但我不确定这在语法上是什么样的,也不确定此实现是否存在潜在问题。

我正在寻找将单独表中的两个 tsvector 字段连接到一个视图中的示例代码,以及关于这在 postgresql 领域中是好还是坏的做法的评论。

【问题讨论】:

当然不能使用索引。你明白吗?分别搜索三个tsvector有什么问题? 我在这里描述的问题只是冰山一角,可以概括为数据库上方的应用服务器和数据库本身之间存在太多的颠簸。因此,我试图将尽可能多的工作保留在数据库中,并尽量减少往返次数。 抱歉,不确定该评论与分别针对三个 tsvector 运行搜索的相关性 - 为什么会影响查询数量? 【参考方案1】:

我也在想同样的事情。我不认为我们应该像这样组合来自多个表的 tsvector。最佳解决方案是:

    在每个表(用户、评估者、连接器)中创建一个新的 tsv 列 使用您要搜索的所有文本更新每个表中的新 tsv 列。例如,在用户表中,您将更新连接 first_name 和 last_name 列的所有记录的 tsv 列。 在新的 tsv 列上创建索引,这将比在单个列上建立索引更快 像往常一样运行查询,让 Postgres “思考”要使用哪些索引。它可能会或可能不会在涉及多个表的查询中使用所有索引。 使用 ANALYZE 和 EXPLAIN 命令查看 Postgres 如何将您的新索引用于特定查询,这将使您深入了解进一步加快处理速度。

这至少是我的方法。我一直在做大量的阅读,并发现人们没有将来自多个表的数据组合到 tsvectors 中。其实我觉得这是不可能的,在创建tsvector的时候可能只能使用当前表的列。

【讨论】:

【参考方案2】:

连接 tsv 向量有效,但根据 cmets,索引可能不会以这种方式使用(不是专家,不能说它是否这样做)。

SELECT * FROM newsletters
LEFT JOIN campaigns ON newsletters.campaign_id=campaigns.id
WHERE newsletters.tsv || campaigns.tsv @@ to_tsquery(unaccent(?))

您想要这样做的原因是搜索像 txt1 & txt2 & txt 3 这样的 AND 字符串,这是非常常见的使用场景。如果您通过 OR WHERE campaigns.tsv @@ to_tsquery(unaccent(?) 简单地拆分搜索,这将不起作用,因为它会尝试匹配两个 tsv 列中的所有 3 个标记,但标记可能位于任一列中。

我发现的一个解决方案是在 table2 更改时使用触发器在 table1 中插入和更新 tsv 列,请参阅:https://dba.stackexchange.com/questions/154011/postgresql-full-text-search-tsv-column-trigger-with-many-to-many 但这不是一个确定的答案,并且使用这么多触发器容易出错并且很麻烦。

官方文档和一些教程还展示了在不使用 tsv 列的情况下将所有需要的列动态连接到 ts 向量中。但目前尚不清楚即时与 tsv 列方法相比要慢多少,我找不到关于此的单一基准或解释。文档简单地说:

另一个优点是搜索会更快,因为它不会 有必要重做 to_tsvector 调用以验证索引匹配。 (这在使用 GiST 索引时比使用 GIN 索引更重要;请参阅 第 12.9 节。)表达式索引方法更易于设置, 但是,它需要更少的磁盘空间,因为 tsvector 表示未显式存储。

从中我能看出的是,tsv 列可能会浪费资源并且只会使事情复杂化,但很高兴看到一些硬数字。但是如果你可以像这样连接 tsv 列,那么我想这与在 WHERE 子句中这样做没有什么不同。

【讨论】:

以上是关于将源自不同表的两个 postgresql tsvector 字段连接到单个 postgresql 视图中,以启用联合全文搜索的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 中的字符串替换源自一个额外的字符串数组

PostgreSQL——代价估计

PostgreSQL——代价估计

PostgreSQL——代价估计

PostgreSQL——代价估计

PostgreSQL 用一个查询增加一个表的序列