W idealnym przypadku nie używasz dokumentów JSON dla uporządkowanych, zwykłych danych, którymi chcesz manipulować w relacyjnej bazie danych. Zamiast tego użyj znormalizowanego projektu relacyjnego .
JSON jest przede wszystkim przeznaczony do przechowywania całych dokumentów, które nie wymagają manipulacji w RDBMS. Związane z:
Aktualizacja wiersza w Postgres zawsze powoduje zapisanie nowej wersji całego wiersza. To podstawowa zasada modelu MVCC Postgresa . Z punktu widzenia wydajności nie ma znaczenia, czy zmienisz pojedynczy fragment danych w obiekcie JSON, czy wszystkie: należy napisać nową wersję wiersza.
Dlatego rady w instrukcji :
Dane JSON podlegają tym samym zagadnieniom dotyczącym kontroli współbieżności, co każdy inny typ danych przechowywanych w tabeli. Chociaż przechowywanie dużych dokumentów jest możliwe, należy pamiętać, że każda aktualizacja powoduje zablokowanie całego wiersza na poziomie wiersza. Rozważ ograniczenie dokumentów JSON do rozmiaru umożliwiającego zarządzanie, aby zmniejszyć rywalizację o blokady między aktualizacjami transakcji. Idealnie byłoby, gdyby każdy dokument JSON reprezentował niepodzielne dane, które narzucają reguły biznesowe, nie mogą być dalej dzielone na mniejsze dane, które można modyfikować niezależnie.
Istota tego: aby zmodyfikować cokolwiek wewnątrz obiektu JSON, musisz przypisać zmodyfikowany obiekt do kolumny. Postgres zapewnia ograniczone możliwości tworzenia i manipulowania json
danymi oprócz swoich możliwości przechowywania. Arsenał narzędzi znacznie się powiększył z każdą nową wersją od wersji 9.2. Ale zasada pozostaje: zawsze musisz przypisać całkowicie zmodyfikowany obiekt do kolumny, a Postgres zawsze zapisuje nową wersję wiersza dla każdej aktualizacji.
Niektóre techniki pracy z narzędziami Postgres 9.3 lub nowszym:
Ta odpowiedź przyciągnęła mniej więcej tyle samo głosów przeciw, co wszystkie moje inne odpowiedzi razem na SO . Ludziom nie podoba się ten pomysł: znormalizowany projekt jest lepszy w przypadku danych niedynamicznych. Ten doskonały wpis na blogu Craiga Ringera wyjaśnia bardziej szczegółowo:
Erwin Brandstetter
źródło
json
ijsonb
podobnych. Oba przechowują dane JSON,jsonb
robią to w znormalizowanej formie binarnej, która ma pewne zalety (i kilka wad). stackoverflow.com/a/10560761/939860 Ani typ danych jest dobra dla bycia manipulowania dużo wewnątrz bazy danych. Żaden typ dokumentu nie jest. Cóż, jest to dobre dla małych, mało ustrukturyzowanych dokumentów JSON. Ale duże, zagnieżdżone dokumenty byłyby głupotą.Jeśli możesz zaktualizować do Postgresql 9.5,
jsonb_set
polecenie jest dostępne, jak wspominali inni.W każdej z poniższych instrukcji SQL pominąłem
where
klauzulę dotyczącą zwięzłości; oczywiście chciałbyś to dodać.Nazwa aktualizacji:
Zastąp tagi (w przeciwieństwie do dodawania lub usuwania tagów):
Zastąpienie drugiego tagu (z indeksem 0):
Dołącz tag (
będzie działać, o ile będzie mniej niż 999 tagów; zmiana argumentu 999 na 1000 lub więcej generuje błąd. Wydaje się, że nie ma to już miejsca w Postgres 9.5.3; można użyć znacznie większego indeksu) :Usuń ostatni tag:
Złożona aktualizacja (usuń ostatni tag, wstaw nowy tag i zmień nazwę):
Należy zauważyć, że w każdym z tych przykładów w rzeczywistości nie aktualizujesz ani jednego pola danych JSON. Zamiast tego tworzysz tymczasową, zmodyfikowaną wersję danych i przypisujesz tę zmodyfikowaną wersję z powrotem do kolumny. W praktyce wynik powinien być taki sam, ale pamiętanie o tym powinno sprawić, że złożone aktualizacje, takie jak ostatni przykład, będą bardziej zrozumiałe.
W złożonym przykładzie istnieją trzy transformacje i trzy wersje tymczasowe: Po pierwsze, ostatni tag jest usuwany. Następnie ta wersja jest przekształcana przez dodanie nowego tagu. Następnie druga wersja jest przekształcana poprzez zmianę
name
pola. Wartość wdata
kolumnie zostanie zastąpiona wersją ostateczną.źródło
jsonb_set
wywołania zewnętrznego są danymi wyjściowymi z wywołania wewnętrznego, a dane wejściowe do tego wywołania wewnętrznego są wynikiemdata #- '{tags,-1}'
. To znaczy oryginalne dane z usuniętym ostatnim tagiem.{tags,0}
, oznaczałoby to „pierwszy element tablicytags
”, pozwalając mi nadać nową wartość temu elementowi. Używając dużej liczby zamiast 0, zamiast zastępować istniejący element w tablicy, dodaje nowy element do tablicy. Jeśli jednak tablica faktycznie zawiera więcej niż 999 999 999 elementów, spowoduje to zastąpienie ostatniego elementu zamiast dodania nowego.To pojawi się w 9.5 w postaci jsonb_set autorstwa Andrew Dunstana w oparciu o istniejące rozszerzenie jsonbx, które działa z 9.4
źródło
jsonb_build_object()
, ponieważx->key
nie zwraca pary klucz-obiekt, aby wypełnić ją potrzebnąjsonb_set(target, path, jsonb_build_object('key',x->key))
.Dla tych, którzy napotkali ten problem i chcą bardzo szybkiej naprawy (i utknęli w wersji 9.4.5 lub wcześniejszej), oto co zrobiłem:
Stworzenie tabeli testowej
Zaktualizuj instrukcję, aby zmienić nazwę właściwości JSONB
Ostatecznie przyjęta odpowiedź jest prawidłowa, ponieważ nie można zmodyfikować pojedynczego fragmentu obiektu jsonb (w wersji 9.4.5 lub wcześniejszej); jednak można rzutować obiekt jsonb na łańcuch (:: TEXT), a następnie manipulować łańcuchem i rzutować z powrotem na obiekt jsonb (:: jsonb).
Istnieją dwa ważne zastrzeżenia
Powiedziawszy to, natknąłem się na sytuację, w której musiałem zaktualizować schemat zawartości w obiektach jsonb i był to najprostszy sposób, aby osiągnąć dokładnie to, o co prosił oryginalny plakat.
źródło
\u0000
puste znaki, przykład pokazał pełny obraz. Dzięki za to!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
To pytanie zostało postawione w kontekście postgres 9.4, jednak nowi widzowie przychodzący na to pytanie powinni mieć świadomość, że w postgres 9.5 pod-dokument Operacje Create / Update / Delete na polach JSONB są natywnie obsługiwane przez bazę danych, bez konieczności rozbudowy Funkcje.
Zobacz: operatory i funkcje modyfikujące JSONB
źródło
zaktualizuj atrybut „name”:
a jeśli chcesz usunąć na przykład atrybuty „nazwa” i „tagi”:
źródło
Napisałem dla siebie małą funkcję, która działa rekurencyjnie w Postgres 9.4. Miałem ten sam problem (dobrze, że rozwiązali część tego bólu głowy w Postgres 9.5). W każdym razie tutaj jest funkcja (mam nadzieję, że działa dobrze):
Oto przykładowe użycie:
Jak widać, analizuje głęboko i aktualizuje / dodaje wartości w razie potrzeby.
źródło
jsonb_build_object
zostało wprowadzone w wersji 9.5Może: UPDATE test SET data = '"moja-inna-nazwa"' :: json WHERE id = 1;
Zadziałało w moim przypadku, gdzie dane są typu json
źródło
Matheus de Oliveira stworzył przydatne funkcje dla operacji JSON CRUD w postgresql. Można je importować za pomocą dyrektywy \ i. Zwróć uwagę na widelec jsonb funkcji, jeśli jsonb, jeśli typ danych.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
źródło