tsvectors 的串联导致 Postgres 9.4.6 中的语法错误

Concatenation of tsvectors results in a syntax error in Postgres 9.4.6

在 SQL 查询中连接来自 setweight 的 tsvectors 时,会抛出语法错误:

ERROR: syntax error at or near "||"

如果我用 setweight 返回的单个 tsvector 尝试它,它工作正常,如果我尝试将整个东西包装在另一个 to_tsvector 调用中,它会出错,原因是没有 to_tsvector(tsvector) 函数,所以串联确实形成了一个 tsvector。

SELECT *, ts_rank_cd(textsearch, query) AS score
FROM products, plainto_tsquery('awesome shirt') query, 
   setweight(to_tsvector(coalesce(title, '')), 'A') ||
   setweight(to_tsvector(coalesce(description, '')), 'B') ||
   setweight(to_tsvector(coalesce(tags, '')), 'C') ||
   setweight(to_tsvector(coalesce(vendor, '')), 'D') textsearch
WHERE shop_url='somedomain.com' AND query @@ textsearch
ORDER BY score DESC
LIMIT 20 OFFSET 0;

我试过将它包装在一个子查询中,但这使它成为一条记录,这会导致 ts_rank_cd 出现问题,因为它期望 textsearch 是 tsvector 类型。我怎样才能让这个连接的 tsvector 在此查询中工作?

假设列 titledescription 等应该引用回 table products ...

您看到的语法错误与文本搜索本身无关。这应该有效:

SELECT *, ts_rank_cd(textsearch, query) AS score
FROM   products
CROSS  JOIN LATERAL plainto_tsquery('awesome shirt') query
CROSS  JOIN LATERAL (
   SELECT setweight(to_tsvector(coalesce(title      , '')), 'A')
       || setweight(to_tsvector(coalesce(description, '')), 'B')
       || setweight(to_tsvector(coalesce(tags       , '')), 'C')
       || setweight(to_tsvector(coalesce(vendor     , '')), 'D')
   ) ts (textsearch)
WHERE  ...

为什么?

因为这个:

SELECT ...
FROM   products, plainto_tsquery('awesome shirt') query ...

FROM 子句中的隐式 CROSS JOIN LATERALfunctions 允许省略 LATERAL 关键字。逗号大部分(见末尾的 link)等同于 CROSS JOIN.

也适用于此:

SELECT ...
FROM   products
     , plainto_tsquery('awesome shirt') query
     , setweight(to_tsvector(coalesce(title, '')), 'A')  -- just another function
...

因此:

It works fine if I try it with a single tsvector returned by setweight

但是相同的短语法不允许其他 表达式 喜欢 setweight(...) || setweight(...)。这些需要包含在 SELECT 语句中,该语句需要显式 LATERAL 关键字以允许引用 FROM 列表中的 "lateral" table。就像上面演示的那样。或者,更短:

SELECT *, ts_rank_cd(textsearch, query) AS score
FROM   products
     , plainto_tsquery('awesome shirt') query
     , LATERAL (
   SELECT setweight(to_tsvector(coalesce(title      , '')), 'A')
       || setweight(to_tsvector(coalesce(description, '')), 'B')
       || setweight(to_tsvector(coalesce(tags       , '')), 'C')
       || setweight(to_tsvector(coalesce(vendor     , '')), 'D')
   ) ts (textsearch)
WHERE  ...

有关 CROSS JOINLATERAL 的更多解释的相关答案: