/ / Запитване за точно съвпадение на кодовете на json в Postgresql (Exacly тези клавиши) - postgresql, jsonb

Заявка за точно съвпадение на кодовете на json в Postgresql (Exacly тези клавиши) - postgresql, jsonb

Опитвам се да попитам за редове, които съдържат клавишите ["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.