2014-06-18 11 views
29

Cercare di trovare tutte le righe in cui una determinata colonna json contiene un oggetto vuoto, {}. Questo è possibile con gli array JSON, o se sto cercando una chiave specifica nell'oggetto. Ma voglio solo sapere se l'oggetto è vuoto. Non riesco a trovare un operatore che lo farà.Come interrogare una colonna JSON per oggetti vuoti?

dev=# \d test 
    Table "public.test" 
    Column | Type | Modifiers 
--------+------+----------- 
    foo | json | 

dev=# select * from test; 
    foo 
--------- 
    {"a":1} 
    {"b":1} 
    {} 
(3 rows) 

dev=# select * from test where foo != '{}'; 
ERROR: operator does not exist: json <> unknown 
LINE 1: select * from test where foo != '{}'; 
            ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 
dev=# select * from test where foo != to_json('{}'::text); 
ERROR: operator does not exist: json <> json 
LINE 1: select * from test where foo != to_json('{}'::text); 
            ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 
dwv=# select * from test where foo != '{}'::json; 
ERROR: operator does not exist: json <> json 
LINE 1: select * from test where foo != '{}'::json; 
            ^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 

risposta

55

c'è uguaglianza (o disuguaglianza) operatore per il tipo di dati json nel suo complesso, perché l'uguaglianza è difficile da stabilire. Il numero di telefonojsonb è in Postgres 9.4, dove è possibile. Maggiori dettagli in questa risposta correlata su dba.SE (ultimo capitolo):

Casting entrambi i lati della espressione text permette = o <> operatori, ma non è del tutto affidabile, ci sono molte possibili rappresentazioni di testo per lo stesso valorejson.

Per questo caso particolare, però, funziona bene:

select * from test where foo::text <> '{}'::text; 
+0

Fresh from the oven: http://www.postgresql.org/about/news/1557/ – opyate

+2

Probabilmente ovvio ma questo funziona anche per gli array vuoti, basta sostituire il {} con [] – hobberwickey

+1

Se stai cercando strutture nidificate, il seguente potrebbe essere qualcosa che potreste usare: 'select * from test where foo - >> 'property' = '[]';' dove la struttura potrebbe essere qualcosa del tipo: '{" proprietà ": []," foo ":" bar "}' – Dynom

1

In 9.3 è possibile contare le coppie di ciascun oggetto e filtrare quelli con nessuna

create table test (foo json); 
insert into test (foo) values 
('{"a":1, "c":2}'), ('{"b":1}'), ('{}'); 

select * 
from test 
where (select count(*) from json_each(foo) s) = 0; 
foo 
----- 
{} 

o prova l'esistenza, probabilmente più veloce per i grandi oggetti

select * 
from test 
where not exists (select 1 from json_each(foo) s); 

Entrambe le tecniche funzioneranno in modo impeccabile rdless of formating

+0

Perché il 's' dopo la chiamata json_each in questi esempi? Quale scopo serve? – Stratus3D

+0

@ Stratus3D È l'alias obbligatorio per una sottoquery, in questo caso una funzione. –

Problemi correlati