Вложенный поиск без ключей в jsonb в PostgreSql - PullRequest
0 голосов
/ 12 июня 2018

Вопрос касается выбора из JSON в PostgreSQL.

Например, приложение содержит данные перевода в jsonb:

{
  "en":{
    "locale":"en",
    "title":"Title",
    "textShort":"Short text",
    "textFull":"Full text"
  }
  "ru":{
    "locale":"ru",
    "title":"Заголовок",
    "textShort":"Короткий текст",
    "textFull":"Подробный текст"
  }
}

Этот запрос успешно работает:

select * 
from content_records 
where translations::json->'en'->>'title' like '%Title.';

Но этот запрос требует информации о локали, но дело в том, что мы ничего не знаем о локалях, и поиск должен быть выполнен для каждой локали, например:

select * 
from content_records 
where translations::json->'any locale'->>'title' like '%Title.';

В MySQL он работает как:

select * 
from content_records 
where LOWER(JSON_EXTRACT(translations, '$.*.title')) LIKE LOWER(:title);

В PostgreSQL есть аналогичная функция: json_extract_path, но для нее требуются ключевые слова, и вы не можете пропустить ключ, как символ * в MySQL.

Вопрос в том -как сделать выбор вложенного JSON в этой ситуации?

1 Ответ

0 голосов
/ 12 июня 2018

К сожалению, в Postgres сначала нужно «отменить» удаление ключей.

Примерно так:

select t.*, cr.translations
from content_records cr
  cross join lateral jsonb_object_keys(translations) as t(locale)
where lower(cr.translations -> t.locale ->> 'title') like '%title';

Обратите внимание, что если заголовок совпадает более чем в одной локали, вы получите одну строку для каждой соответствующей локали.Если вы не хотите этого, вы можете сделать следующее:

select cr.*
from content_records cr
where exists (select *
              from jsonb_object_keys(cr.translations) as t(locale)
              where lower(cr.translations -> t.locale ->> 'title') like '%title')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...