sql >> Base de Datos >  >> RDS >> PostgreSQL

Cómo consultar matrices jsonb con el operador IN

Respuesta corta

Puede usar la función jsonb_array_elements() en una unión lateral y usa su resultado value en expresiones complejas en el WHERE cláusula:

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

Distinto

La consulta puede devolver filas duplicadas cuando se cumplen las condiciones del filtro en más de un elemento de la matriz en una sola fila, por ejemplo,

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)    

Por lo tanto, puede ser razonable usar DISTINCT en el SELECT lista:

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

o EXISTS en el WHERE cláusula, que puede ser un poco más rápida:

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

También puede seleccionar elementos de matriz coincidentes en los casos en que se necesite esta información:

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)

Rendimiento

El jsonb_array_elements() La función es cara. Para tablas más grandes, el uso de la función puede ser cuestionable debido a la gran carga del servidor y al largo tiempo de ejecución de una consulta.

Mientras que un índice GIN se puede usar para consultas con @> operador:

CREATE INDEX ON test USING GIN (test_content)

en el caso de la función esto no es posible. Las consultas admitidas por el índice pueden ser hasta varias docenas de veces más rápidas que las que utilizan la función.