Опитвам се да попитам за редове, които съдържат клавишите ["kommune", "fylke", "år"] в jsonb колони, наречени data_filters.
Доколкото мога да видя postgres има само този оператор ?&
което ми дава всички редове, които имат всички тези ключове, но не искам редове, които също имат (например) ключовото "хоби". Досега използвам това:
select * from main_dataitem
where array["fylke", "kommune", "år"] @> ARRAY(select jsonb_object_keys(data_filters))
and ARRAY(select jsonb_object_keys(data_filters)) @> array["fylke", "kommune", "år"];
Това обаче не изглежда като оптимално решение, всеки има по-добър начин да попита за това?
Само за да е ясно, това не дава желания резултат, защото отговаря на редове, които съдържат посочените клавиши и плюс произволни клавиши (които не съм посочил):
select * from main_dataitem where data_filters ?& array["fylke", "kommune", "år"];
Отговори:
0 за отговор № 1Вероятно трябва да е най-бързата (с изключение на чистата функция C):
create or replace function jsonb_same_keys(p_json jsonb, p_keys text[])
returns boolean immutable strict language plpythonu as $$
import json
j = json.loads(p_json).keys()
return sorted(j) == sorted(p_keys)
$$;
select jsonb_same_keys("{"1":2,"2":1}"::jsonb, array["2","1"]);
╔═════════════════╗
║ jsonb_same_keys ║
╠═════════════════╣
║ t ║
╚═════════════════╝
Разбира се, трябва да имате инсталиран Python и езиковото разширение в PostgreSQL: create extension plpythonu;
0 за отговор № 2
Не съм сигурен дали това все още е релевантно (тъй като това беше зададено> преди 1 година), но току-що се сблъсках по този въпрос.
Ако използвате jsonb, можете да използвате и -
оператор. Това премахва един или повече комплекта ключове от стойността на JSON. Ако се запитвате само за обекти, които имат посочените клавиши, резултатът от тази операция трябва да е празен JSON ({}
).
Така че въпросът ще бъде:
select * from main_dataitem where (data_filters - array["fylke", "kommune", "år"]) = "{}";
Свързани с отговора на @Abelisto (само за пълнота), можете също да направите извличането и сортирането на клавишите JSON, като използвате jsonb_object_keys
/ json_object_keys
функция. Нещо като това:
select * from main_dataitem where array(select x from jsonb_object_keys(data_filters) as x order by x) = array["fylke", "kommune", "år"];
В моя собствен набор от данни за тестване (~ 330k редове), аз открих, че това е значително по-бавно от първата алтернатива, предложена по-горе все пак.
Също така за записа, направих това в PostgreSQL 10.0.