Ich möchte, dass PostgreSQL das Ergebnis einer Abfrage als ein JSON-Array zurückgibt. Gegeben
create table t (a int primary key, b text);
insert into t values (1, 'value1');
insert into t values (2, 'value2');
insert into t values (3, 'value3');
Ich hätte gerne etwas ähnliches
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
oder
{"a":[1,2,3], "b":["value1","value2","value3"]}
(Eigentlich wäre es sinnvoller, beide zu kennen). Ich habe einige Dinge wie ausprobiert
select row_to_json(row) from (select * from t) row;
select array_agg(row) from (select * from t) row;
select array_to_string(array_agg(row), '') from (select * from t) row;
Und ich fühle mich nah, aber nicht wirklich da. Sollte ich mir andere Unterlagen als 9.15 ansehen? JSON-Funktionen und Operatoren ?
Ich bin mir übrigens nicht sicher über meine Idee. Ist das eine übliche Designentscheidung? Ich denke, ich könnte natürlich das Ergebnis (zum Beispiel) der ersten der oben genannten 3 Abfragen nehmen und es in der Anwendung leicht bearbeiten, bevor ich es dem Client bereitstelle, aber wenn PostgreSQL das endgültige JSON-Objekt direkt erstellen kann, Es wäre einfacher, da ich noch keine Abhängigkeit von einer JSON-Bibliothek in meine Anwendung aufgenommen habe.
quelle
Antworten:
TL; DR
für ein JSON-Array von Objekten und
für ein JSON-Objekt von Arrays.
Liste der Objekte
In diesem Abschnitt wird beschrieben, wie Sie ein JSON-Array von Objekten generieren, wobei jede Zeile in ein einzelnes Objekt konvertiert wird. Das Ergebnis sieht folgendermaßen aus:
9.3 und höher
Die
json_agg
Funktion erzeugt dieses Ergebnis sofort. Es findet automatisch heraus, wie seine Eingabe in JSON konvertiert und zu einem Array zusammengefasst wird.Es gibt keine
jsonb
(in 9.4 eingeführte) Version vonjson_agg
. Sie können die Zeilen entweder zu einem Array zusammenfassen und dann konvertieren:oder
json_agg
mit einer Besetzung kombinieren :Meine Tests legen nahe, dass die Aggregation zu einem Array etwas schneller ist. Ich vermute, dass dies daran liegt, dass die Besetzung das gesamte JSON-Ergebnis analysieren muss.
9.2
9.2 verfügt nicht über die Funktionen
json_agg
oderto_json
, daher müssen Sie die älteren verwendenarray_to_json
:Sie können optional einen
row_to_json
Anruf in die Abfrage aufnehmen:Dadurch wird jede Zeile in ein JSON-Objekt konvertiert, die JSON-Objekte werden als Array zusammengefasst und anschließend wird das Array in ein JSON-Array konvertiert.
Ich konnte keinen signifikanten Leistungsunterschied zwischen den beiden feststellen.
Objekt von Listen
In diesem Abschnitt wird beschrieben, wie Sie ein JSON-Objekt generieren, wobei jeder Schlüssel eine Spalte in der Tabelle und jeder Wert ein Array der Werte der Spalte ist. Das Ergebnis sieht folgendermaßen aus:
9,5 und höher
Wir können die
json_build_object
Funktion nutzen:Sie können die Spalten auch aggregieren, eine einzelne Zeile erstellen und diese dann in ein Objekt konvertieren:
Beachten Sie, dass ein Aliasing der Arrays unbedingt erforderlich ist, um sicherzustellen, dass das Objekt die gewünschten Namen hat.
Welches klarer ist, ist Ansichtssache. Wenn Sie die
json_build_object
Funktion verwenden, empfehle ich dringend, ein Schlüssel / Wert-Paar in eine Zeile zu setzen, um die Lesbarkeit zu verbessern.Sie könnten auch
array_agg
anstelle von verwendenjson_agg
, aber meine Tests zeigen, dassjson_agg
das etwas schneller ist.Es gibt keine
jsonb
Version derjson_build_object
Funktion. Sie können zu einer einzelnen Zeile zusammenfassen und Folgendes konvertieren:Im Gegensatz zu den anderen Abfragen für diese Art von Ergebnis
array_agg
scheint die Verwendung etwas schneller zu seinto_jsonb
. Ich vermute, dass dies auf das Overhead-Parsen und Validieren des JSON-Ergebnisses von zurückzuführen istjson_agg
.Oder Sie können eine explizite Besetzung verwenden:
Die
to_jsonb
Version ermöglicht es Ihnen, die Besetzung zu vermeiden und ist laut meinen Tests schneller; Ich vermute erneut, dass dies auf den Aufwand für das Parsen und Validieren des Ergebnisses zurückzuführen ist.9.4 und 9.3
Die
json_build_object
Funktion war neu in 9.5, daher müssen Sie in früheren Versionen aggregieren und in ein Objekt konvertieren:oder
je nachdem ob du willst
json
oderjsonb
.(9.3 hat nicht
jsonb
.)9.2
In 9.2 existiert nicht einmal
to_json
. Sie müssen verwendenrow_to_json
:Dokumentation
Die Dokumentation zu den JSON-Funktionen finden Sie unter JSON-Funktionen .
json_agg
befindet sich auf der Seite mit den Aggregatfunktionen .Design
Wenn die Leistung wichtig ist, stellen Sie sicher, dass Sie Ihre Abfragen mit Ihrem eigenen Schema und Ihren eigenen Daten vergleichen, anstatt meinen Tests zu vertrauen.
Ob es sich um ein gutes Design handelt oder nicht, hängt wirklich von Ihrer spezifischen Anwendung ab. In Bezug auf die Wartbarkeit sehe ich kein besonderes Problem. Dies vereinfacht Ihren App-Code und bedeutet, dass in diesem Teil der App weniger zu warten ist. Wenn PG Ihnen genau das Ergebnis liefern kann, das Sie sofort benötigen, ist der einzige Grund, warum ich mir vorstellen kann, es nicht zu verwenden, Leistungsüberlegungen. Das Rad und alles nicht neu erfinden.
Nullen
Aggregatfunktionen geben normalerweise etwas zurück,
NULL
wenn sie über Nullzeilen arbeiten. Wenn dies eine Möglichkeit ist, möchten Sie sie möglicherweiseCOALESCE
vermeiden. Einige Beispiele:Oder
Dank an Hannes Landeholm für diesen Hinweis
quelle
to_json
anstelle vonrow_to_json
undarray_to_json
SELECT json_agg((column1, column2, ...)) FROM t
- beachten Sie die zusätzlichen Klammern. Dies ist möglicherweise nicht offensichtlich "out of the box".Auch wenn Sie ausgewähltes Feld aus Tabelle und aggregiert dann als Array.
Das Ergebnis wird kommen.
quelle