En första omedelbar åtgärd skulle vara att göra frågan du har lite snabbare:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
EXISTS
semi-join undviker duplicering av rader i den mellanliggande tabellen när flera arrayobjekt matchar - och behovet av DISTINCT ON
i den yttre frågan. Men det är bara lite snabbare än.
Kärnproblemet är att du vill testa för ett intervall av heltalsvärden , medan existerande jsonb
operatörer
tillhandahåller inte sådan funktionalitet.
Det finns olika sätt runt detta. Utan att veta något av detta, här är en "smart" lösning som löser det givna exemplet. Tricket är att dela upp intervallet till distinkta värden och använda jsonb
inneslutningsoperatör @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Stöds av en jsonb_path_ops
GIN-index:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Men om dina intervall sträcker sig över mer än en hand full av heltalsvärden, behöver du något mer generiskt. Som alltid , den bästa lösningen beror på hela situationen:Datadistribution, värdefrekvenser, typiska intervall i frågor, NULL-värden möjliga?, radstorlek, läs-/skrivmönster, gör alla jsonb
värde har en eller flera matchande age
nyckel? ...
Relaterat svar med specialiserat, mycket snabbt index:
Relaterat: