PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Актуализация на JSONB масив за конкретен елемент

PostgreSQL 11+

Ако вече сте на PostgreSQL v. 11 (заради нов JSONB поддръжка на типово преобразуване ) най-добрият ви залог вероятно ще бъде персонализирана функция, написана на Perl или Python.

Тъй като предпочитам Python 3, ето функционален пример:

CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
    RETURNS jsonb
    TRANSFORM FOR TYPE jsonb
    LANGUAGE plpython3u
AS $$
v_new = val
tmp = v_new
for e in path_to_array:
    tmp = tmp[e]

for item in tmp:
    if (entry_filters is None or entry_filters.items() <= item.items()):
        item.update(replacement)

return v_new
$$;

...което след това може да се използва както следва:

UPDATE configuration
SET
  config = jsonb_replace_in_array(
    config,
    '{data}',
    '{"value":"changed"}'::jsonb,
    '{"oid":"11.5.15.1.4","instance":"1.1.4"}'::jsonb
  )
WHERE config->'data' @> '[{"oid":"11.5.15.1.4","instance":"1.1.4"}]';

Така че да, условието се дублира, но само за да се ограничи броят на редовете, които да се докоснат на първо място.

За да работите в обикновена инсталация на PostgreSQL 11, имате нужда от разширения plpython3u и jsonb_plpython3u :

CREATE EXTENSION plpython3u;
CREATE EXTENSION jsonb_plpython3u;

Логиката на Python е обяснена:

for e in path_to_array:
    tmp = tmp[e]

... ни отвежда до масива от записи, които трябва да разгледаме.

for item in tmp:
    if (entry_filters is None or entry_filters.items() <= item.items()):
        item.update(replacement)

...за всеки елемент в масива проверяваме дали критериите за филтър са null (entry_filters is None =съответства на всеки запис) или дали записът „съдържа“ предоставения пример, включително ключове и стойности (entry_filters.items() <= item.items() ).

Ако en запис съвпада, тогава презапишете/добавете съдържание с предоставената замяна.

Надявам се, че това отива в посоката, която търсите.

Разглеждайки текущите възможности на PostgreSQL, свързани с модификацията на JSON, би било много сложно (ако не и сложно) и би довело до много допълнителни разходи, за да се направи същото с чист SQL.

PostgreSQL 9.6+

В случай, че все още нямате налична версия 11, следната функция ще направи същото за сметка на самата обработка на преобразуванията на типове, но ще я запази напълно съвместима с API, така че след като надстроите, единственото нещо, което трябва да направите е замяна на функцията (не се изисква промяна на никакви изрази, използващи тази функция):

CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
    RETURNS jsonb
    LANGUAGE plpython3u
AS $$
import json

v_new = json.loads(val)
t_replace = json.loads(replacement)
t_filters = json.loads(entry_filters)
tmp = v_new
for e in path_to_array:
    tmp = tmp[e]

for item in tmp:
    if (entry_filters is None or t_filters.items() <= item.items()):
        item.update(t_replace)

return json.dumps(v_new)
$$;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Инсталирайте Postgres.app на Mac

  2. Автоматично увеличената стойност не работи в PostgreSQL при използване на EntityFramework Core

  3. Как да използвате подзаявки в SQLAlchemy за създаване на подвижна средна?

  4. Postgress грешка - инсталиране на пакет

  5. Регистриране на одит за PostgreSQL