Una primera medida inmediata sería hacer la consulta que tienes un poco más rápido:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
El EXISTS
semi-join evita la duplicación de filas en la tabla intermedia cuando coinciden varios objetos de matriz, y la necesidad de DISTINCT ON
en la consulta externa. Pero eso es solo un poco más rápido, todavía.
El problema central es que desea probar un rango de valores enteros , mientras jsonb
operadores
no proporciona dicha funcionalidad.
Hay varias maneras de evitar esto. Sin saber nada de esto, aquí hay una solución "inteligente" que resuelve el ejemplo dado. El truco es dividir el rango en valores distintos y usar jsonb
operador de contención @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Compatible con jsonb_path_ops
Índice GIN:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Pero si sus rangos abarcan más de un puñado de valores enteros, necesitará algo más genérico. Como siempre , la mejor solución depende de la situación completa:distribución de datos, frecuencias de valores, rangos típicos en las consultas, ¿valores NULL posibles?, tamaño de fila, patrones de lectura/escritura, todos jsonb
el valor tiene uno o más age
coincidentes ¿llave? ...
Respuesta relacionada con índice especializado muy rápido:
Relacionado: