Първата незабавна мярка би била да направите заявката, която имате, малко по-бърза:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
СЪЩЕСТВУВАТ
semi-join избягва дублирането на редове в междинната таблица, когато множество обекти от масив съвпадат - и необходимостта от DISTINCT ON
във външната заявка. Но това все още е малко по-бързо.
Основният проблем е, че искате да тествате за диапазон от цели числа , докато съществуващ jsonb
оператори
не предоставят такава функционалност.
Има различни начини за това. Без да знаете нищо от това, ето едно "умно" решение, което решава дадения пример. Номерът е да разделите диапазона на отделни стойности и да използвате jsonb
оператор за ограничаване @>код> :
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Поддържа се от jsonb_path_ops
GIN индекс:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Но ако вашите диапазони обхващат повече от ръка, пълна с цели стойности, ще ви трябва нещо по-общо. Както винаги , най-доброто решение зависи от цялостната ситуация:разпределение на данните, честоти на стойности, типични диапазони в заявките, възможни NULL стойности?, размер на реда, модели за четене/запис, прави всеки jsonb
стойността има една или повече съвпадащи възраст
ключ? ...
Свързан отговор със специализиран, много бърз индекс:
Свързани: