10

我有一个由 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 领域中是好还是坏的做法的评论。

4

2 回答 2

1

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

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

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

于 2014-04-02T01:02:39.497 回答
1

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

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 字符串。如果您将搜索简单地拆分为 anOR 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 子句中执行此操作没有什么不同。

于 2016-11-15T15:37:09.197 回答