【问题标题】:Concatenation of tsvectors results in a syntax error in Postgres 9.4.6tsvector 的串联导致 Postgres 9.4.6 中的语法错误
【发布时间】:2019-01-17 09:08:42
【问题描述】:

在 SQL 查询中连接来自 setweight 的 tsvector 时,会引发语法错误:

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 在这个查询中工作?

【问题讨论】:

    标签: sql postgresql postgresql-9.4 lateral-join


    【解决方案1】:

    假设列titledescription 等应该引用回表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 LATERAL函数允许省略 LATERAL 关键字。逗号大部分(见最后的链接)相当于CROSS JOIN

    也适用于此:

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

    因此:

    如果我尝试使用 setweight 返回的单个 tsvector 效果很好

    相同的短句法不允许用于其他表达式,例如setweight(...) || setweight(...)。这些需要包含在SELECT 语句中,该语句需要明确的LATERAL 关键字以允许引用FROM 列表中的“横向”表。如上所示。或者,更短:

    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 的更多解释的相关答案:

    【讨论】:

    • 谢谢!这似乎现在有效。这就解释了为什么单个函数调用不会导致语法错误。
    猜你喜欢
    • 1970-01-01
    • 2021-05-27
    • 2017-04-01
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多