PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

So fragen Sie jsonb-Arrays mit dem IN-Operator ab

Kurze Antwort

Sie können die Funktion jsonb_array_elements() verwenden in einem lateralen Join und verwenden Sie dessen Ergebnis value in komplexen Ausdrücken im WHERE Klausel:

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('b', 'd')
AND value->>'label1' IN ('2', '3')

Eindeutig

Die Abfrage kann doppelte Zeilen zurückgeben, wenn die Filterbedingungen in mehr als einem Element des Arrays in einer einzelnen Zeile erfüllt sind, z. B.

SELECT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |                          test_content                          
--------------------------------------+----------------------------------------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | [{"label": "a", "label1": "1"}, {"label": "b", "label1": "2"}]
(2 rows)    

Daher kann es sinnvoll sein, DISTINCT zu verwenden im SELECT Liste:

SELECT DISTINCT t.* 
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

oder EXISTS im WHERE -Klausel, die etwas schneller sein kann:

SELECT t.*
FROM test t
WHERE EXISTS (
    SELECT 
    FROM jsonb_array_elements(test_content)
    WHERE value->>'label' IN ('a', 'b')
    )

Sie können auch passende Array-Elemente auswählen, falls diese Informationen benötigt werden:

SELECT id, value
FROM test t
CROSS JOIN jsonb_array_elements(test_content)
WHERE value->>'label' IN ('a', 'b')

                  id                  |             value             
--------------------------------------+-------------------------------
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "a", "label1": "1"}
 aa82a8b8-33ef-4937-bd8c-8a4b40960f18 | {"label": "b", "label1": "2"}
(2 rows)

Leistung

Die jsonb_array_elements() Funktion ist teuer. Bei größeren Tabellen kann die Nutzung der Funktion aufgrund der hohen Serverlast und der langen Ausführungszeit einer Abfrage fragwürdig sein.

Während ein GIN-Index für Abfragen mit @> verwendet werden kann Betreiber:

CREATE INDEX ON test USING GIN (test_content)

bei der Funktion ist dies nicht möglich. Vom Index unterstützte Abfragen können bis zu mehrere Dutzend Mal schneller sein als solche, die die Funktion verwenden.