2017-10-12 2 views
0

Ich bin sehr neu in der PG JSONB Feld. Ich habe zum Beispiel eines jsonb Feld des folgendenPostgresql JSONB Traversal

{ 
"RootModule": { 
    "path": [ 
    1 
    ], 
    "tags": { 
    "ModuleBase1": { 
     "value": 40640, 
     "humanstring": "40640" 
    }, 
    "ModuleBase2": { 
    "value": 40200, 
    "humanstring": "40200" 
    } 
    }, 
"children": { 
    "RtuInfoModule": { 
    "path": [ 
     1, 
     0 
    ], 
    "tags": { 
     "in0": { 
     "value": 11172, 
     "humanstring": "11172" 
     }, 
     "in1": { 
     "value": 25913, 
     "humanstring": "25913" 
     } 
etc.... 

Gibt es eine Möglichkeit zur Abfrage X Ebenen tief und suchen den „Tags“ Schlüssel für einen bestimmten Schlüssel enthält.

Sag ich will "ModuleBase2" und "in1" und ich möchte ihre Werte bekommen?

Grundsätzlich suche ich nach einer Abfrage, die ein Jsonb-Feld durchlaufen wird, bis es einen Schlüssel findet und den Wert zurückgibt, ohne die Struktur kennen zu müssen.

In Python oder JS kann eine einfache Schleife oder rekursive Funktion leicht ein Json-Objekt (oder ein Wörterbuch) durchlaufen, bis es einen Schlüssel findet.

Gibt es eine eingebaute Funktion PG muss das tun?

Letztendlich möchte ich dies in Django tun.

Edit: Ich sehe ich Sachen wie

SELECT data.key AS key, data.value as value 
FROM trending_snapshot, jsonb_each(trending_snapshot.snapshot- 
>'RootModule') AS data 
WHERE key = 'tags'; 

tun können, aber ich muss die die Ebenen angeben.

Antwort

0

Sie können eine rekursive Abfrage verwenden, um eine verschachtelte jsonb abzuflachen, siehe this answer. die Abfrage ändern Werte für bestimmte Tasten zu finden (ein Zustand, in where Klausel hinzugefügt werden):

with recursive flat (id, path, value) as (
    select id, key, value 
    from my_table, 
    jsonb_each(data) 
union 
    select f.id, concat(f.path, '.', j.key), j.value 
    from flat f, 
    jsonb_each(f.value) j 
    where jsonb_typeof(f.value) = 'object' 
) 
select id, path, value 
from flat 
where path like any(array['%ModuleBase2.value', '%in1.value']); 

id |      path      | value 
----+--------------------------------------------------+------- 
    1 | RootModule.tags.ModuleBase2.value    | 40200 
    1 | RootModule.children.RtuInfoModule.tags.in1.value | 25913 
(2 rows)  

-Test in SqlFiddle.

+0

Oh wow. Das ist echt cool. Ich danke dir sehr. Die Idee des rekursiven SQL ist jetzt auch neu für mich. Funktioniert super. Und ich stelle mir vor, dass das Bearbeiten der Where-Klausel leicht zu verschiedenen gewünschten Ergebnissen führen kann. –

+0

Ja, Sie können die Ergebnisse kontrollieren, indem Sie die Bedingung ändern. – klin

+0

Du bist ein Lebensretter –

Verwandte Themen