Mam tabelę do przechowywania informacji o moich królikach. To wygląda tak:
create table rabbits (rabbit_id bigserial primary key, info json not null);
insert into rabbits (info) values
('{"name":"Henry", "food":["lettuce","carrots"]}'),
('{"name":"Herald","food":["carrots","zucchini"]}'),
('{"name":"Helen", "food":["lettuce","cheese"]}');
Jak znaleźć króliki, które lubią marchewki? Wymyśliłem to:
select info->>'name' from rabbits where exists (
select 1 from json_array_elements(info->'food') as food
where food::text = '"carrots"'
);
Nie podoba mi się to zapytanie. To bałagan.
Jako pełnoetatowy opiekun królików nie mam czasu na zmianę schematu bazy danych. Chcę tylko odpowiednio karmić moje króliki. Czy istnieje bardziej czytelny sposób wykonania tego zapytania?
json
postgresql
postgresql-9.3
Śnieżna kula
źródło
źródło
Odpowiedzi:
Począwszy od PostgreSQL 9.4, możesz użyć
?
operatora :Możesz nawet zindeksować
?
zapytanie w"food"
kluczu, jeśli zamiast tego przełączysz się na typ jsonb :Oczywiście jako pełnoetatowy opiekun królików prawdopodobnie nie masz na to czasu.
Aktualizacja: Oto demonstracja poprawy wydajności na stole 1000000 królików, gdzie każdy królik lubi dwa pokarmy, a 10% z nich lubi marchewki:
źródło
select * from rabbits where info->'food' != '[]';
create table t (x jsonb); insert into t (x) values ('[1,2,3]'), ('[2,3,4]'), ('[3,4,5]'); select * from t where x @> '2';
. Zauważ, że'2'
jest to numer JSON; nie daj się zwieść cytatom.Możesz użyć operatora @>, aby zrobić to na przykład
źródło
'
tiki otaczające „marchewki” ... pęknie, jeśli je pominiesz, nawet jeśli sprawdzasz liczbę całkowitą. (spędził 3 godziny próbując znaleźć liczbę całkowitą, magicznie działając poprzez owijanie'
tików wokół liczby)'
znacznikami, aby utworzyć łańcuch, ponieważ wszystko jest ciągiem dla SQL w typie JSONB. Na przykład, wartość logiczna:'true'
, string:'"example"'
, całkowita:'123'
.Nie mądrzejszy, ale prostszy:
źródło
Mała zmiana, ale nic nowego w rzeczywistości. Naprawdę brakuje funkcji ...
źródło