При объединении tsvectors из setweight в запросе SQL возникает синтаксическая ошибка:
ERROR: syntax error at or near "||"
Он отлично работает, если я попробую его с одним tsvector, возвращаемым setweight
, и если я попытаюсь обернуть все это в другой вызов 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 работать в этом запросе?
Предполагая, что столбцы title
, description
и т. д. Должны ссылаться на таблицу 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 ...
является неявным CROSS JOIN LATERAL
в предложении FROM
. Пропуск ключевого слова LATERAL
разрешен для функции. И запятая в основном (см. Ссылку в конце) эквивалентна 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
. Как показано выше. Или короче:
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 JOIN
, так и для LATERAL
:
Спасибо! Кажется, теперь это работает. Это объясняет, почему отдельные вызовы функций не вызывали синтаксических ошибок.