Im Idealfall verwenden Sie keine JSON-Dokumente für strukturierte, reguläre Daten, die Sie in einer relationalen Datenbank bearbeiten möchten. Verwenden Sie stattdessen ein normalisiertes relationales Design .
JSON soll in erster Linie ganze Dokumente speichern, die nicht im RDBMS bearbeitet werden müssen. Verbunden:
Durch das Aktualisieren einer Zeile in Postgres wird immer eine neue Version der gesamten Zeile geschrieben. Das ist das Grundprinzip des MVCC-Modells von Postgres . Aus Sicht der Leistung spielt es kaum eine Rolle, ob Sie ein einzelnes Datenelement in einem JSON-Objekt oder alles ändern: Es muss eine neue Version der Zeile geschrieben werden.
So der Rat im Handbuch :
JSON-Daten unterliegen denselben Überlegungen zur Parallelitätskontrolle wie alle anderen Datentypen, wenn sie in einer Tabelle gespeichert werden. Obwohl das Speichern großer Dokumente praktikabel ist, sollten Sie berücksichtigen, dass jedes Update eine Sperre auf Zeilenebene für die gesamte Zeile erhält. Ziehen Sie in Betracht, JSON-Dokumente auf eine überschaubare Größe zu beschränken, um Sperrenkonflikte bei der Aktualisierung von Transaktionen zu verringern. Im Idealfall sollten JSON-Dokumente jeweils ein Atomdatum darstellen, das von den Geschäftsregeln vorgeschrieben wird, und können nicht vernünftigerweise weiter in kleinere Daten unterteilt werden, die unabhängig voneinander geändert werden können.
Das Wesentliche: Um etwas in einem JSON-Objekt zu ändern , müssen Sie der Spalte ein geändertes Objekt zuweisen. Postgres json
bietet zusätzlich zu seinen Speicherfunktionen nur begrenzte Möglichkeiten zum Erstellen und Bearbeiten von Daten. Das Arsenal an Tools ist mit jeder neuen Version seit Version 9.2 erheblich gewachsen. Aber die Haupt bleibt: Sie immer ein komplettes modifizierte Objekt in die Spalte zuweisen und Postgres schreibt immer eine neue Zeile Version für jedes Update.
Einige Techniken zum Arbeiten mit den Werkzeugen von Postgres 9.3 oder höher:
Diese Antwort hat ungefähr so viele Downvotes angezogen wie alle meine anderen Antworten auf SO zusammen . Die Idee scheint den Leuten nicht zu gefallen: Ein normalisiertes Design ist für nicht dynamische Daten überlegen. Dieser ausgezeichnete Blog-Beitrag von Craig Ringer erklärt ausführlicher:
Erwin Brandstetter
quelle
json
undjsonb
gleichermaßen. Beide speichern JSON-Datenjsonb
in einer normalisierten Binärform, die einige Vor- (und wenige Nachteile) aufweist. stackoverflow.com/a/10560761/939860 Keiner der Datentypen eignet sich für viele Manipulationen in der Datenbank. Kein Dokumenttyp ist. Nun, es ist gut für kleine, kaum strukturierte JSON-Dokumente. Aber große, verschachtelte Dokumente wären auf diese Weise eine Torheit.Wenn Sie ein Upgrade auf Postgresql 9.5 durchführen können, ist der
jsonb_set
Befehl verfügbar, wie bereits erwähnt.In jeder der folgenden SQL-Anweisungen habe ich die
where
Klausel der Kürze halber weggelassen . Natürlich möchten Sie das wieder hinzufügen.Name aktualisieren:
Ersetzen Sie die Tags (im Gegensatz zum Hinzufügen oder Entfernen von Tags):
Ersetzen des zweiten Tags (0-indiziert):
Fügen Sie ein Tag hinzu (
dies funktioniert, solange weniger als 999 Tags vorhanden sind. Wenn Sie dasArgument 999 auf 1000 oder höher ändern, wird ein Fehler generiert. Dies scheint in Postgres 9.5.3 nicht mehr der Fall zu sein. Es kann ein viel größerer Index verwendet werden.) ::Entfernen Sie das letzte Tag:
Komplexes Update (Löschen Sie das letzte Tag, fügen Sie ein neues Tag ein und ändern Sie den Namen):
Es ist wichtig zu beachten, dass Sie in jedem dieser Beispiele kein einzelnes Feld der JSON-Daten aktualisieren. Stattdessen erstellen Sie eine temporäre, geänderte Version der Daten und weisen diese geänderte Version wieder der Spalte zu. In der Praxis sollte das Ergebnis das gleiche sein, aber wenn Sie dies berücksichtigen, sollten komplexe Aktualisierungen wie im letzten Beispiel verständlicher werden.
In dem komplexen Beispiel gibt es drei Transformationen und drei temporäre Versionen: Erstens wird das letzte Tag entfernt. Diese Version wird dann durch Hinzufügen eines neuen Tags transformiert. Als nächstes wird die zweite Version durch Ändern des
name
Feldes transformiert . Der Wert in derdata
Spalte wird durch die endgültige Version ersetzt.quelle
jsonb_set
Anruf die Ausgabe des inneren Anrufs ist und dass die Eingabe für diesen inneren Anruf das Ergebnis von istdata #- '{tags,-1}'
. Dh die Originaldaten mit dem zuletzt entfernten Tag.{tags,0}
würde, würde das "das erste Element des Arraystags
" bedeuten und mir erlauben, diesem Element einen neuen Wert zu geben. Indem Sie eine große Zahl anstelle von 0 verwenden, anstatt ein vorhandenes Element im Array zu ersetzen, wird dem Array ein neues Element hinzugefügt. Wenn das Array jedoch tatsächlich mehr als 999.999.999 Elemente enthält, würde dies das letzte Element ersetzen, anstatt ein neues hinzuzufügen.Dies kommt in 9.5 in Form von jsonb_set von Andrew Dunstan, basierend auf einer vorhandenen Erweiterung jsonbx , die mit 9.4 funktioniert
quelle
jsonb_build_object()
, dax->key
kein Schlüssel-Objekt-Paar zurückgegeben wird, um die von Ihnen benötigten Daten zu füllenjsonb_set(target, path, jsonb_build_object('key',x->key))
.Für diejenigen, die auf dieses Problem stoßen und eine sehr schnelle Lösung wünschen (und auf 9.4.5 oder früher stecken bleiben), habe ich Folgendes getan:
Erstellung einer Testtabelle
Aktualisieren Sie die Anweisung, um den Namen der jsonb-Eigenschaft zu ändern
Letztendlich ist die akzeptierte Antwort insofern richtig, als Sie ein einzelnes Stück eines jsonb-Objekts (in 9.4.5 oder früher) nicht ändern können. Sie können das jsonb-Objekt jedoch in eine Zeichenfolge (:: TEXT) umwandeln und dann die Zeichenfolge bearbeiten und in das jsonb-Objekt (:: jsonb) zurückverwandeln.
Es gibt zwei wichtige Vorbehalte
Nachdem dies gesagt wurde, stieß ich auf eine Situation, in der ich das Schema für den Inhalt in den jsonb-Objekten aktualisieren musste, und dies war der einfachste Weg, um genau das zu erreichen, was das ursprüngliche Poster verlangte.
quelle
\u0000
Nullzeichen ersetzen kann. Das Beispiel zeigt das vollständige Bild. Danke dafür!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Diese Frage wurde im Zusammenhang mit Postgres 9.4 gestellt. Neue Betrachter, die zu dieser Frage kommen, sollten sich jedoch darüber im Klaren sein, dass in Postgres 9.5 die Vorgänge zum Erstellen / Aktualisieren / Löschen von Unterdokumenten für JSONB-Felder von der Datenbank nativ unterstützt werden, ohne dass eine Erweiterung erforderlich ist Funktionen.
Siehe: JSONB zum Ändern von Operatoren und Funktionen
quelle
Aktualisieren Sie das Attribut 'Name':
und wenn Sie zum Beispiel die Attribute 'name' und 'tags' entfernen möchten:
quelle
Ich habe eine kleine Funktion für mich geschrieben, die in Postgres 9.4 rekursiv funktioniert. Ich hatte das gleiche Problem (gut, dass sie einige dieser Kopfschmerzen in Postgres 9.5 gelöst haben). Wie auch immer, hier ist die Funktion (ich hoffe, es funktioniert gut für Sie):
Hier ist ein Beispiel für die Verwendung:
Wie Sie sehen können, analysieren Sie tief im Inneren und aktualisieren / fügen Sie Werte hinzu, wo dies erforderlich ist.
quelle
jsonb_build_object
es in 9.5 eingeführt wurdeVielleicht: UPDATE test SET data = '"mein-anderer-Name"' :: json WHERE id = 1;
Es hat in meinem Fall funktioniert, in dem Daten vom Typ JSON sind
quelle
Matheus de Oliveira hat in postgresql praktische Funktionen für JSON CRUD-Operationen erstellt. Sie können mit der Direktive \ i importiert werden. Beachten Sie die jsonb-Verzweigung der Funktionen, wenn jsonb Ihr Datentyp ist.
9.3 json https://gist.github.com/matheusoliveira/9488951
9.4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
quelle