[Python] Postgresql json columns was: Psycopg2 e serializzazione delle SELECT in JSON
Daniele Varrazzo
piro a develer.com
Gio 16 Ott 2014 18:16:10 CEST
On 2014-10-16 16:38, Carlos Catucci wrote:
> Approfitto del thread su psycopg2 per formulare una domnada dborder
> line
> all'OT.
>
> Sto cercando ddi usre delle colonne JSON con Postgres 9.3/Django 1.6+.
> Ovvio che devo usare (*) delle rwa query. Solo che fatico a ottenere un
> risultato con una struttura di questo tipo:
>
> data = '{ "A": { "B": [ { "C": 1, "D": 2 }, { "C": 3, "D": 4 }, {
> "C":1,
> "D": 6, "E": 3 } ] } }'
>
> per fare una query dove mi deve tornare tutti i record, per dire che
> abbianno
>
> tabella.data->'A'->'B'->'C' == 1
>
> ho provato a usare strutture funzioni built-in di Postgres ma senza
> riuscire a cavare il ragno dal buco. Nella migliore delle query ottengo
> un
> resultset vuoto, nelle altre (quasi sempre) dei simpaticissimi errori.
>
> Qualcuno ha avuto problemi similari o una qualche idea su dove posso
> trovare un esempio con una query tipo questa? Premetto che se invece
> che
> una array di hash (dei dict in python) avessi un array di valori (una
> lista insomma) avrei la soluzione ma cosi' ci sto dando di matto.
Non ci ho ancora giocato troppo con le funzioni json di postgres.
Guardando i doc, json_populate_recordset sembra promettente: converte
una lista json in un recordset. Devi definire un tipo che contiene i
dati che ti servono (e' sufficiente che contenga il campo su cui devi
filtrare, gli altri vengono scaricati):
piro=# create type tmp as ("C" int, "D" int);
CREATE TYPE
piro=# select * from json_populate_recordset(null::tmp,
'{ "A": { "B": [ { "C": 1, "D": 2 }, { "C": 3, "D": 4 }, {
"C":1, "D": 6, "E": 3 } ] } }'::json -> 'A' -> 'B');
C | D
---+---
1 | 2
3 | 4
1 | 6
(3 rows)
A questo punto "e' facile" tirare un paio di sottoquery ed ottenere solo
i record per cui esiste un valore di questo "srotolato" per cui C = 1.
piro=# create table mydata(id serial primary key, data json);
CREATE TABLE
piro=# insert into mydata (data) values ('{ "A": { "B": [ { "C": 1,
"D": 2 }, { "C": 3, "D": 4 }, { "C":1, "D": 6, "E": 3 } ] } }');
INSERT 0 1
piro=# insert into mydata (data) values ('{ "A": { "B": [ { "C": 0,
"D": 2 }, { "C": 3, "D": 4 }, { "C": 0, "D": 6, "E": 3 } ] } }');
INSERT 0 1
Il record 1 matcha, il 2 no. Puoi usare:
piro=# select d.* from mydata d
where exists (
select 1 from (
select id,
(json_populate_recordset(null::tmp, data -> 'A' ->
'B'))."C"
from mydata) x
where "C" = 1
and x.id = d.id);
id | data
----+---------------------------------------------------------------------------
1 | { "A": { "B": [ { "C": 1, "D": 2 }, { "C": 3, "D": 4 }, {
"C":1, "D": 6, .
|."E": 3 } ] } }
(1 row)
Non credo sia possibile ottimizzare questo tipo di query con un indice
comunque. Ma quello neanche con un array sarebbe stato agevole.
-- Daniele
Maggiori informazioni sulla lista
Python