Объединение tsvectors приводит к синтаксической ошибке в Postgres 9.4.6

При объединении 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 работать в этом запросе?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
0
581
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предполагая, что столбцы 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:

Спасибо! Кажется, теперь это работает. Это объясняет, почему отдельные вызовы функций не вызывали синтаксических ошибок.

Brandon Anzaldi 10.08.2018 03:11

Другие вопросы по теме