PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Aktualizacja tablicy JSONB dla określonego elementu

PostgreSQL 11+

Jeśli jesteś już na PostgreSQL v. 11 (z powodu nowy JSONB obsługa konwersji typów ) najlepszym rozwiązaniem byłaby prawdopodobnie niestandardowa funkcja napisana w Perlu lub Pythonie.

Ponieważ wolę Pythona 3, oto funkcjonalny przykład:

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
$$;

...które następnie można wykorzystać w następujący sposób:

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"}]';

Więc tak, warunek jest zduplikowany, ale tylko w celu ograniczenia liczby wierszy do dotknięcia w pierwszej kolejności.

Aby faktycznie pracować na zwykłej instalacji PostgreSQL 11, potrzebujesz rozszerzeń plpython3u i jsonb_plpython3u :

CREATE EXTENSION plpython3u;
CREATE EXTENSION jsonb_plpython3u;

Wyjaśnienie logiki Pythona:

for e in path_to_array:
    tmp = tmp[e]

...sprowadza nas do tablicy wpisów, które musimy przejrzeć.

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

...dla każdego elementu w tablicy sprawdzamy, czy kryteria filtrowania są null (entry_filters is None =pasuje do dowolnego wpisu) lub czy wpis "zawiera" podany przykład, w tym klucze i wartości (entry_filters.items() <= item.items() ).

Jeśli wpis pasuje, nadpisz/dodaj zawartość dostarczonym zamiennikiem.

Mam nadzieję, że to idzie w kierunku, w którym szukasz.

Patrząc na obecne możliwości PostgreSQL związane z modyfikacją JSON, byłoby to bardzo złożone (jeśli nie skomplikowane) i wprowadzałoby wiele narzutów, aby zrobić to samo z czystym SQL.

PostgreSQL 9.6+

W przypadku, gdy nie masz jeszcze dostępnej wersji 11, poniższa funkcja zrobi to samo kosztem obsługi samej konwersji typów, ale zachowa ją w pełni zgodną z API, więc po aktualizacji jedyne, co musisz zrobić zastępuje funkcję (nie są wymagane żadne zmiany w instrukcjach korzystających z tej funkcji):

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. Instalacja PostgreSQL na OSX dla rozwoju Rails

  2. Jak rzutować ciąg na liczbę całkowitą i mieć 0 w przypadku błędu rzutowania za pomocą PostgreSQL?

  3. wypełnij kolumnę ostatnią wartością z partycji w postgresql

  4. jak zapytać o min lub max inet/cidr za pomocą postgres

  5. Jak uzyskać kluczowe pola dla tabeli w funkcji plpgsql?