Как выполнить запрос, используя поля внутри нового типа данных PostgreSQL JSON?

216

Я ищу некоторые документы и / или примеры для новых функций JSON в PostgreSQL 9.2.

В частности, учитывая ряд записей JSON:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

Как бы я написал SQL, чтобы найти запись по имени?

В ванильном SQL:

SELECT * from json_data WHERE "name" = "Toby"

Официальное руководство разработчика довольно мало:

Обновить я

Я собрал суть, детализирующую, что в настоящее время возможно с PostgreSQL 9.2 . Используя некоторые пользовательские функции, можно делать такие вещи, как:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

Обновление II

Теперь я переместил свои функции JSON в их собственный проект:

PostSQL - набор функций для преобразования PostgreSQL и PL / v8 в совершенно потрясающее хранилище документов JSON

Тоби хеде
источник
3
Совсем недавно я нашел этот пост в блоге Мэтта Шинкеля, который подробно объясняет запросы JSON в PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@knowbody Этот пост на самом деле о запросах JSONB, который совершенно отличается от JSON. Мой плохой за то, что я не прояснил этот пост.
Мэтью Шинкель

Ответы:

177

Postgres 9.2

Я цитирую Эндрю Данстана в списке pgsql-хакеров :

На каком-то этапе, возможно, будут некоторые функции, обрабатывающие json (в отличие от json-производить), но не в 9.2.

Не мешает ему привести пример реализации в PLV8, который должен решить вашу проблему.

Postgres 9,3

Предлагает арсенал новых функций и операторов для добавления «json-processing».

Ответ на оригинальный вопрос в Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

Расширенный пример:

Для больших таблиц вы можете добавить индекс выражения для увеличения производительности:

Postgres 9,4

Добавляет jsonb(b для «двоичного», значения хранятся как родные типы Postgres) и еще больше функциональности для обоих типов. В дополнение к индексам выражений, упомянутым выше, jsonbтакже поддерживаются индексы GIN, btree и hash , причем GIN является наиболее мощным из них.

Руководство идет так далеко, что предлагает:

Как правило, большинство приложений предпочитают хранить данные JSON как jsonb , если только нет особых потребностей, таких как устаревшие предположения о порядке расположения ключей объекта.

Жирный акцент мой.

Производительность выигрывает от общего улучшения индексов GIN.

Postgres 9,5

Полные jsonbфункции и операторы. Добавьте больше функций для управления jsonbна месте и для отображения.

Эрвин Брандштеттер
источник
1
Спасибо, я очень быстро столкнулся с проблемами типа, используя подход PLV8. Выглядит многообещающе, но не очень удобно в данный момент.
Тоби Хеде
@TobyHede: Думаю, нам придется ждать 9,3.
Эрвин Брандстеттер
1
@JoeShaw: Спасибо, я соответственно обновился и добавил ссылку на Postgres Wiki.
Эрвин Брандштеттер,
@ErwinBrandstetter, если я ищу ГДЕ элемент - >> 'correct' = 'TRUE'; и JSON выглядит так: "correct": "TRUE", как правильно запрашивать логические термины?
Shiraj
@Shiraj: Пожалуйста, задавайте новые вопросы как вопрос . Комментарии не место.
Эрвин Брандштеттер
87

С Postgres 9.3+ просто используйте ->оператор. Например,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

см. http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ для некоторых хороших примеров и учебного пособия.

Meekohi
источник
2
В приведенном выше примере вы должны иметь поле с именем dataс документом JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Дайте нам знать, как выглядят ваши данные и какой запрос не выполняется.
Meekohi
stackoverflow.com/questions/22667401/…
Мохамед Эль Махаллави
6
Как вы можете запросить, если есть массив? Я вижу оператор # >>, но не знаю, как его использовать!
Мохаммед Эль Махаллави
В этом запросе выбора я могу использовать подстановочный знак? То естьSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Бхарат
Ответ @ Meekohi работает хорошо: конкретно мне не нужно, ::jsonкак описано в других сообщениях. Также обратите внимание, что ->оператор выдаст ошибку, если вы попытаетесь получить доступ к несуществующему свойству (т. Е. Если вы пошатнулись JSON):ERROR: column "jsonPropertyYouWant" does not exist
Red Pea
19

В Postgres 9.3 используйте -> для доступа к объекту. 4 примера

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

рельсы с

SELECT data->'params'->0 as data FROM smart_elements;

возвращается

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

Вы можете продолжить вложение

SELECT data->'params'->0->'type' as data FROM smart_elements;

возвращение

 data
------
 1
(1 row)
joseAndresGomezTovar
источник