Wie frage ich mithilfe von Feldern im neuen PostgreSQL JSON-Datentyp ab?


216

Ich suche nach einigen Dokumenten und / oder Beispielen für die neuen JSON-Funktionen in PostgreSQL 9.2.

Insbesondere bei einer Reihe von JSON-Datensätzen:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

Wie würde ich die SQL schreiben, um einen Datensatz nach Namen zu finden?

In Vanilla SQL:

SELECT * from json_data WHERE "name" = "Toby"

Das offizielle Entwicklerhandbuch ist ziemlich spärlich:

Update I.

Ich habe eine Übersicht zusammengestellt, die ausführlich beschreibt, was derzeit mit PostgreSQL 9.2 möglich ist . Mit einigen benutzerdefinierten Funktionen können Sie Folgendes tun:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

Update II

Ich habe jetzt meine JSON-Funktionen in ein eigenes Projekt verschoben:

PostSQL - eine Reihe von Funktionen zur Umwandlung von PostgreSQL und PL / v8 in einen fantastischen JSON-Dokumentenspeicher


3
Erst vor kurzem fand ich diesen Blog - Post von Matt Schinckel, die im Detail erklärt JSON in PostgreSQL Abfragen schinckel.net/2014/05/25/querying-json-in-postgres
Knowbody

1
@knowbody In diesem Beitrag geht es eigentlich darum, JSONB abzufragen, was sich deutlich von JSON unterscheidet. Mein schlechtes, weil ich das in der Post nicht klarer gemacht habe.
Matthew Schinckel

Antworten:


177

Postgres 9.2

Ich zitiere Andrew Dunstan auf der Liste der pgsql-Hacker :

Irgendwann wird es möglicherweise einige json-verarbeitende Funktionen geben (im Gegensatz zu json-produzierenden), aber nicht in 9.2.

Verhindert nicht, dass er eine Beispielimplementierung in PLV8 bereitstellt , die Ihr Problem lösen sollte.

Postgres 9.3

Bietet ein Arsenal neuer Funktionen und Operatoren, um "json-processing" hinzuzufügen.

Die Antwort auf die ursprüngliche Frage in Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

Erweitertes Beispiel:

Bei größeren Tabellen möchten Sie möglicherweise einen Ausdrucksindex hinzufügen, um die Leistung zu steigern:

Postgres 9.4

Adds jsonb(b für "binär", Werte werden als native Postgres-Typen gespeichert) und noch mehr Funktionalität für beide Typen. Zusätzlich zu den oben erwähnten Expressionsindizes werden jsonbauch GIN-, btree- und Hash-Indizes unterstützt, wobei GIN der wirksamste davon ist.

Das Handbuch geht so weit, Folgendes vorzuschlagen:

Im Allgemeinen sollten die meisten Anwendungen es vorziehen, JSON-Daten als zu speichern jsonb , es sei denn, es gibt ganz spezielle Anforderungen, wie z. B. ältere Annahmen zur Reihenfolge der Objektschlüssel.

Meine kühne Betonung.

Die Leistung profitiert von allgemeinen Verbesserungen der GIN-Indizes.

Postgres 9.5

Komplette jsonbFunktionen und Bediener. Fügen Sie weitere Funktionen hinzu, die Sie jsonban Ort und Stelle bearbeiten und anzeigen können.


1
Vielen Dank, ich bin mit dem PLV8-Ansatz sehr schnell auf Typprobleme gestoßen. Sieht vielversprechend aus, ist aber momentan nicht wirklich brauchbar.
Toby Hede

@TobyHede: Dann müssen wir wohl auf 9.3 warten.
Erwin Brandstetter

1
@ JoeShaw: Danke, ich habe entsprechend aktualisiert und einen Link zum Postgres-Wiki hinzugefügt.
Erwin Brandstetter

@ErwinBrandstetter wenn ich nach WHERE elem suche - >> 'korrekt' = 'WAHR'; und der JSON sieht folgendermaßen aus: "richtig": "WAHR", wie kann man logische Begriffe richtig abfragen?
Shiraj

@ Shiraj: Bitte stellen Sie die neuen Fragen als Frage . Kommentare sind nicht der richtige Ort.
Erwin Brandstetter

87

Verwenden Sie bei Postgres 9.3+ einfach den ->Operator. Beispielsweise,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

Unter http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ finden Sie einige schöne Beispiele und ein Tutorial.


2
Im obigen Beispiel sollte ein Feld datamit einem JSON-Dokument benannt sein : {images:{thumbnail:{url:'thumbnail.jpg'}}}. Lassen Sie uns wissen, wie Ihre Daten aussehen und welche Abfrage fehlschlägt.
Meekohi


6
Wie können Sie abfragen, ob ein Array vorhanden ist? Ich sehe den Operator # >>, aber keine Ahnung, wie man ihn benutzt!
Mohamed El Mahallawy

Kann ich in dieser Auswahlabfrage einen Platzhalter verwenden? DhSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat

@ Meekohis Antwort funktioniert gut: Insbesondere brauchte ich nicht ::jsonwie in anderen Beiträgen beschrieben. Beachten Sie auch, dass der ->Bediener einen Fehler ausgibt, wenn Sie versuchen, auf eine Eigenschaft zuzugreifen, die nicht vorhanden ist (dh wenn Sie JSON versetzt haben):ERROR: column "jsonPropertyYouWant" does not exist
Die rote Erbse

19

Verwenden Sie mit postgres 9.3 -> für den Objektzugriff. 4 Beispiel

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

Schienen c

SELECT data->'params'->0 as data FROM smart_elements;

kehrt zurück

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

Sie können weiter verschachteln

SELECT data->'params'->0->'type' as data FROM smart_elements;

Rückkehr

 data
------
 1
(1 row)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.