2016-04-20 7 views
1

ich eine PostgreSQL-Tabelle haben (Kreaturen), die wie folgt aussieht:PostgreSQL jsonb_array_elements mit Array von Hash-Elemente

| id <integer> | json <jsonb> | 
------------------------------- 
|  1  | {"name": "Grooper", "weaknesses":[{"type":"Fire", "value":2},{"type":"Dark", "value":2}]} | 
|  2  | {"name": "Zik", "weaknesses":[{"type":"Fire", "value":2}]} | 

Ich versuche, eine Abfrage zu erstellen, die auf Schwäche Art Filter, so dass ich gefiltert werden können alle Kreaturen mit Schwächen Arten FireoderDark (enthalten entweder ein), aber mit Schwächen des Typs auf Kreaturen FireundDark (müssen beide enthalten) abfragen, auch.

Ich habe eine Abfrage herausgefunden, dass mit FireoderDark funktioniert:

select 
    distinct c.* 
from 
    creatures c, 
    jsonb_array_elements(json->'weaknesses') as weakness 
where weakness->'type' ?| array['Fire','Dark'] 

Wie kann ich diese Abfrage

auf Kreaturen der Typen Fire und Dark filtern zu arbeiten?

UPDATE:

Ich habe eine Abfrage, die zu erreichen scheint, was ich will, aber es nicht hübsch aussehen. Irgendwelche Tipps?

SELECT * FROM creatures 
WHERE 'Fire' in (SELECT jsonb_array_elements(json->'weaknesses')->>'type') 
AND 'Dark' in (SELECT jsonb_array_elements(json->'weaknesses')->>'type') 

Antwort

1

Das Problem hierbei ist, dass Sie die jsonb Werte innerhalb des Arrays „in aussehen“ müssen, so dass Sie nicht die ?& Betreiber nutzen können. Stattdessen finden die entsprechenden Tasten mit dem ? Operator und wählen Sie nur die Zeilen, die zwei Treffer haben:

SELECT DISTINCT id, json 
FROM creatures 
JOIN LATERAL jsonb_array_elements(json->'weaknesses') ON value ? 'Dark' OR value ? 'Fire' 
GROUP BY 1, 2 
HAVING count(id) = 2; 

By the way, wenn id (? Vielleicht Primärschlüssel) einzigartig ist dann SELECT DISTINCT ON (id) id, json ... ist viel schneller, weil die jsonb Dokument muss nicht überprüft werden, um Duplikate zu entfernen.

+0

Danke, spielte mit diesem ein bisschen herum und sieht gut aus. –

Verwandte Themen