Uma primeira medida imediata seria tornar a consulta que você tem um pouco mais rápida:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
O
EXISTE
semi-join evita a duplicação de linhas na tabela intermediária quando vários objetos de matriz correspondem - e a necessidade de DISTINCT ON
na consulta externa. Mas isso é apenas ligeiramente mais rápido, ainda. O problema principal é que você deseja testar um intervalo de valores inteiros , enquanto jsonb existente operadores não fornecem tal funcionalidade.
Existem várias maneiras de contornar isso. Sem saber nada disso, aqui está uma solução "inteligente" que resolve o exemplo dado. O truque é dividir o intervalo em valores distintos e usar o
jsonb
operador de contenção @>
:SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Suportado por um
jsonb_path_ops
Índice GIN:CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Mas se seus ranges abrangem mais do que uma mão cheia de valores inteiros, você precisará de algo mais genérico. Como sempre , a melhor solução depende da situação completa:distribuição de dados, frequências de valores, intervalos típicos em consultas, valores NULL possíveis?, tamanho da linha, padrões de leitura/gravação, todos
jsonb
value tem um ou mais age
correspondentes chave? ... Resposta relacionada com índice especializado e muito rápido:
Relacionado: