先ほど、
postgres / psycopg2でjsonbサポートを有効にする方法を書き
ました 。 今日、JSONのような列のデータを要求する方法を試しました。
このテーマ
に関するドキュメントはありますが、さまざまな操作がどのように機能するかは完全にはわかりませんでした。
CREATE TABLE json_test ( id serial primary key, data jsonb ); INSERT INTO json_test (data) VALUES ('{}'), ('{"a": 1}'), ('{"a": 2, "b": ["c", "d"]}'), ('{"a": 1, "b": {"c": "d", "e": true}}'), ('{"b": 2}');
リクエストは機能しました。チェックするすべてのデータを取得しましょう。
SELECT * FROM json_test; id | data
次に、結果をフィルタリングします。 使用できる演算子はいくつかありますが、タイプとしてjsonbを選択した理由は後で説明します。
平等jsonbでは、2つのJSONオブジェクトが同一であることを確認できます。
SELECT * FROM json_test WHERE data = '{"a":1}'; id | data
制限事項また、別のオブジェクトを含むjsonオブジェクトを取得することもできます。 「サブセットであること」:
SELECT * FROM json_test WHERE data @> '{"a":1}';
言う:-キーaと値1で始まるすべてのオブジェクトを教えてください:
id | data
両方向の制限:
この場合、クエリは空のオブジェクトと2番目のオブジェクトの完全一致を出力します。
SELECT * FROM json_test WHERE data <@ '{"a":1}'; id | data
キー/アイテムの存在演算子の最後のバッチでは、キー(または配列内の文字列型の要素)の存在を確認します。
id | data
リストから任意のキーを持つオブジェクトを取得します。
SELECT * FROM json_test WHERE data ?| array['a', 'b']; id | data
そして、リストから完全に一致するキーを持つオブジェクトのすべての値:
SELECT * FROM json_test WHERE data ?& array['a', 'b']; id | data
バイパスするキーkey-> pathに一致するレコードをフィルタリングすることもできます。 単純な場合、制限演算子を使用する方が簡単ですが、複雑な演算子ではなく、それらを省くことができません。 これらの操作はSELECTで使用できますが、WHERE句で適用する方がより興味深いです。
SELECT * FROM json_test WHERE data ->> 'a' > '1';
キーaが1である連想要素の値のすべてのレコードを取得します。
数値ではなくテキスト値を使用する必要があることに注意してください。
id | data
オブジェクトと配列のプリミティブを比較できます:
SELECT * FROM json_test WHERE data -> 'b' > '1'; id | data
配列とオブジェクトは数字以上のものであることがわかります。
より深い道も見ることができます。
SELECT * FROM json_test WHERE data
要素bに子オブジェクトcがあり、cが文字列「d」に等しいオブジェクトを取得します。
id | data
JSONオブジェクトではなく、テキストを返すこれらのステートメントのバージョンもあります。 最後のリクエストの場合、これは(実際に文字列を取得したいバージョンの)JSONオブジェクトと比較する必要がないことを意味します。
SELECT * FROM json_test WHERE data
したがって、ここまではすべて問題ありません。 異なるデータを扱うことができ、jsonbインデックスでも同じデータを使用できます。 ただし、より注意深い読者は、ルートからのオブジェクトパスを持つJSONデータを処理していることに気付いているかもしれません。 これは次のようにする必要はありません。配列も有効なJSONであり、実際に有効な例は次のとおりです。
SELECT 'null'::json, 'true'::json, 'false'::json, '2'::json, '1.0001'::json, '"abc"'::json, '1E7'::jsonb;
最後のエントリは、jsonb型であり、標準形式に変換されることに注意してください。
json | json | json | json | json | json | jsonb
JSON nullもSQL NULLとは異なります。
では、混合型のオブジェクトをJSON列に格納するとどうなりますか?
INSERT INTO json_test (data) VALUES ('[]'), ('[1,2,"a"]'), ('null'), ('1E7'), ('"abc"'); SELECT * FROM json_test; id | data
構造全体が問題なく推定されました。 これらのオブジェクトとクエリを使用できるかどうかを確認しましょう。
同等性チェックは正常に機能します。
SELECT * FROM json_test WHERE data = '{"a":1}'; SELECT * FROM json_test WHERE data = 'null';
制限も期待どおりに機能します。
SELECT * FROM json_test WHERE data @> '{"a":1}'; SELECT * FROM json_test WHERE data <@ '{"a":1}';
キーと既存のアイテムも機能します。 当然のことながら、単一のリクエストは、配列の要素とオブジェクトのキーに一致します。
SELECT * FROM json_test WHERE data ? 'a'; id | data
SELECT * FROM json_test WHERE data ?| array['a', 'b']; id | data
SELECT * FROM json_test WHERE data ?& array['a', 'b']; id | data
しかし、「get」のキーまたは要素を作成し始めるとすぐに、問題が発生します。
(どうやら、この記事の著者は執筆時点でPotgreSQL 9.4 bettaバージョンをインストールしていたため、クエリの一部にエラーがあり、9.4.1ですべてのクエリが処理されました):
SELECT * FROM json_test WHERE data ->> 'a' > '1'; ERROR: cannot call jsonb_object_field_text (jsonb ->> text operator) on an array
非スカラー値がある場合でも、キーパスバイパスを使用できます。
SELECT * FROM json_test WHERE data
文字列(jsonキーが必要)または整数(配列インデックス)のキーパスの構文に注意してください。
これは非常に厳しい制限を課します。 MondgoDBでこのようなことがどのように機能するかはわかりません。
しかし、将来的に、配列とjsonオブジェクトのデータを1つの列に格納する場合、将来、いくつかの問題が発生する可能性があります。 しかし、すべてが失われるわけではありません。 ベースオブジェクトに基づいて文字列を取得できます。
SELECT * FROM json_test WHERE data @> '{}'; id | data
次に、このリクエストを上記のリクエストと組み合わせることができます。
SELECT * FROM json_test WHERE data @> '{}' AND data ->> 'a' > '1'; id | data
実際、Postgresでは、データ@> '{}が最初に来ることを確認する必要すらありません。
しかし、配列データ型のみが必要な場合はどうでしょうか? 同じトリックを使用できることがわかりました。
SELECT * FROM json_test WHERE data @> '[]'; id | data
また、他の演算子と組み合わせることができます。
SELECT * FROM json_test WHERE data @> '[]' AND data ->> 1 = '2'; id | data
@>演算子のエントリはjsonb列でのみ使用できるため、通常のjson列の混合データをリクエストすることはできません。
次は?
Postgresのjsonbはサードパーティのプロジェクトであると考え、現在ORM djangoでjson(b)クエリに取り組んでいます。 Django 1.7では、次のような検索関数を記述できます。
しかし、最後のセットの名前が機能するかどうかはわかりません。 「get」という名前は少し普遍的であり、入力タイプの代わりに別の名前を使用できますが、整数と文字列のみが有効です。