В идеале вы не должны использовать документы JSON для структурированных обычных данных, которыми вы хотите управлять внутри реляционной базы данных. Вместо этого используйте нормализованный реляционный дизайн .
JSON в первую очередь предназначен для хранения целых документов, которыми не нужно управлять внутри СУБД. Связанный:
При обновлении строки в Postgres всегда записывается новая версия всей строки. Это основной принцип модели MVCC Постгреса . С точки зрения производительности вряд ли имеет значение, изменяете ли вы отдельный фрагмент данных внутри объекта JSON или все его: необходимо написать новую версию строки.
Таким образом, совет в руководстве :
Данные JSON подлежат тем же соображениям контроля параллелизма, что и любой другой тип данных при хранении в таблице. Хотя хранение больших документов практически возможно, имейте в виду, что при любом обновлении блокируется на уровне всей строки. Рассмотрите возможность ограничения документов JSON до управляемого размера, чтобы уменьшить конфликт блокировок между транзакциями обновления. В идеале каждый документ JSON должен представлять элементарные данные, которые диктуются бизнес-правилами, которые не могут быть разумно разделены на более мелкие данные, которые можно было бы изменять независимо.
Суть его: изменить что-либо внутри объекта JSON, вы должны назначить измененный объект столбцу. Postgres предоставляет ограниченные средства для создания json
данных и управления ими в дополнение к своим возможностям хранения. Арсенал инструментов существенно расширялся с каждым новым выпуском, начиная с версии 9.2. Но принцип остается: вы всегда должны назначать столбцу полностью измененный объект, а Postgres всегда записывает новую версию строки для любого обновления.
Некоторые методы работы с инструментами Postgres 9.3 или новее:
Этот ответ привлек столько же отрицательных голосов, сколько все мои другие ответы на SO вместе . Людям эта идея, кажется, не нравится: нормализованный дизайн лучше для нединамических данных. Этот отличный пост в блоге Крейга Рингера объясняет более подробно:
Эрвин Брандштеттер
источник
json
иjsonb
т.п. Оба хранят данные JSONjsonb
в нормализованной двоичной форме, которая имеет некоторые преимущества (и несколько недостатков). stackoverflow.com/a/10560761/939860 Ни один из типов данных не подходит для большого количества манипуляций внутри базы данных. Нет типа документа. Что ж, это нормально для небольших, плохо структурированных документов JSON. Но в таком случае большие вложенные документы были бы глупостью.Если вы можете обновить до Postgresql 9.5,
jsonb_set
команда доступна, как уже упоминали другие.В каждом из следующих операторов SQL
where
для краткости я опустил этот пункт; очевидно, вы захотите добавить это обратно.Название обновления:
Замените теги (в отличие от добавления или удаления тегов):
Замена второго тега (с индексом 0):
Добавить тег (
это будет работать, пока тегов меньше 999; изменение аргумента с 999 на 1000 или выше вызывает ошибку. В Postgres 9.5.3 этого больше нет; можно использовать гораздо больший индекс) :Удалите последний тег:
Комплексное обновление (удалить последний тег, вставить новый тег и изменить имя):
Важно отметить, что в каждом из этих примеров вы не обновляете ни одного поля данных JSON. Вместо этого вы создаете временную измененную версию данных и назначаете эту измененную версию обратно столбцу. На практике результат должен быть таким же, но, учитывая это, комплексные обновления, такие как последний пример, будут более понятными.
В сложном примере есть три преобразования и три временных версии: во-первых, удаляется последний тег. Затем эта версия преобразуется путем добавления нового тега. Далее вторая версия трансформируется путем изменения
name
поля. Значение вdata
столбце заменяется окончательной версией.источник
jsonb_set
вызова является выходом из внутреннего вызова, а вход для этого внутреннего вызова является результатомdata #- '{tags,-1}'
. Т.е. исходные данные с удаленным последним тегом.{tags,0}
, это означало бы «первый элемент массиваtags
», что позволило бы мне дать новое значение этому элементу. Используя большое число вместо 0, вместо замены существующего элемента в массиве, он добавляет новый элемент в массив. Однако, если в массиве действительно было более 999 999 999 элементов, это заменило бы последний элемент, а не добавило бы новый.Это появится в версии 9.5 в виде появится в версии jsonb_set от Эндрю Данстана на основе существующего расширения jsonbx, которое работает с 9.4.
источник
jsonb_build_object()
, потому чтоx->key
, not возвращает пару ключ-объект, для заполнения, которое вам нужноjsonb_set(target, path, jsonb_build_object('key',x->key))
.Для тех, кто столкнулся с этой проблемой и хочет очень быстро исправить (и застрял на 9.4.5 или более ранней версии), вот что я сделал:
Создание тестовой таблицы
Оператор обновления для изменения имени свойства jsonb
В конечном итоге принятый ответ верен в том смысле, что вы не можете изменить отдельную часть объекта jsonb (в 9.4.5 или ранее); однако вы можете преобразовать объект jsonb в строку (:: TEXT), а затем манипулировать строкой и вернуть ее к объекту jsonb (:: jsonb).
Есть два важных предостережения
При этом я столкнулся с ситуацией, когда мне пришлось обновить схему для содержимого в объектах jsonb, и это был самый простой способ выполнить именно то, что просил исходный плакат.
источник
\u0000
нулевые символы, пример показал полную картину. Спасибо за это!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Этот вопрос был задан в контексте postgres 9.4, однако новые зрители, приходящие к этому вопросу, должны знать, что в postgres 9.5 операции создания / обновления / удаления субдокумента в полях JSONB изначально поддерживаются базой данных без необходимости расширения функции.
См .: Операторы и функции изменения JSONB
источник
обновить атрибут name:
и если вы хотите удалить, например, атрибуты 'name' и 'tags':
источник
Я написал для себя небольшую функцию, которая рекурсивно работает в Postgres 9.4. У меня была такая же проблема (хорошо, что они решили часть этой головной боли в Postgres 9.5). В любом случае вот функция (я надеюсь, что она вам подходит):
Вот пример использования:
Как видите, он глубоко анализирует и при необходимости обновляет / добавляет значения.
источник
jsonb_build_object
было введено в 9.5Возможно: UPDATE test SET data = '"my-other-name"' :: json WHERE id = 1;
Это сработало с моим случаем, где данные представляют собой тип json
источник
Матеус де Оливейра создал удобные функции для операций JSON CRUD в postgresql. Их можно импортировать с помощью директивы \ i. Обратите внимание на вилку jsonb функций if jsonb, если ваш тип данных.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
источник