web-dev-qa-db-ja.com

空のオブジェクトのjson列をクエリする方法は?

特定のjson列に空のオブジェクト{}が含まれるすべての行を検索する。これは、JSON配列を使用するか、オブジェクト内の特定のキーを探している場合に可能です。しかし、オブジェクトが空かどうかを知りたいだけです。これを行う演算子を見つけることができないようです。

 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.
51
sbeam

データ型json全体に等号(または不等号)演算子はありません。確立するのが難しい。 jsonb Postgres 9.4以降では、これが可能な場合を考えてください。 dba.SEに関するこの関連する回答の詳細(最終章):

SELECT DISTINCT json_column ... または ... GROUP BY json_column同じ理由で失敗します(等号演算子なし)。

式の両側をtextにキャストすると、= または <>演算子ですが、samejson値には多くのテキスト表現が存在する可能性があるため、通常は信頼できません。

ただし、この特定のケース空のオブジェクト)の場合はうまく動作します:

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

PostgreSQL 9.5の時点では、JSONデータを使用したこのタイプのクエリは不可能です。一方、私はそれが非常に有用であり、それに対する要求を作成することに同意します:

https://postgresql.uservoice.com/forums/21853-general/suggestions/12305481-check-if-json-is-empty

気軽に投票してください。うまくいけば実装されます!

5
Pensierinmusica

9.3では、各オブジェクトのペアをカウントし、なしでペアをフィルタリングすることができます

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 
-----
 {}

または存在をテストします。大きなオブジェクトの場合はおそらく高速です

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

どちらのフォーマットも、フォーマットに関係なく問題なく機能します

2
Clodoaldo Neto

空のJSON配列[]も関連する可能性があります。

その後、これは両方の[]および{}

select * from test where length(foo::text) > 2 ;
1
weinerk