次のようなjson配列を保持する「user」というフィールドがあります。
"user"
:
[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]
今私は次のようなクエリが必要です:
select count from tablename where id = "1"
PostgreSQL 9.4では、jsonオブジェクトの配列から特定のフィールドcount
を取得できません。
正規化されたスキーマに値を格納する方がはるかに効率的です。つまり、現在の設定で動作させることもできます。
このテーブル定義を仮定すると:
_CREATE TABLE tbl (tbl_id int, usr jsonb);
_
「user」は 予約語 であり、列名として使用するには二重引用符が必要です。それをしないでください。代わりにusr
を使用します。
クエリは、(現在は削除されている)コメントのように簡単ではありません。
_SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
_
3つの基本的なステップがあります:
_WHERE t.usr @> '[{"_id":"1"}]'
_は、JSON配列内の一致するオブジェクトを持つ行を識別します。この式では、jsonb
列で一般的なGINインデックスを使用することも、より専門的な演算子クラス_jsonb_path_ops
_を使用することもできます。
_CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
_
追加されたWHERE
句は論理的に冗長ですが、インデックスを使用する必要があります。結合句の式は同じ条件を適用しますが、これまでに条件を満たしているすべての行の配列をネスト解除した後のみです。インデックスのサポートにより、Postgresは、最初から適格オブジェクトを含む行のみを処理します。小さなテーブルではあまり問題にならず、大きなテーブルとhugeの違いがあり、適格な行はほとんどありません。
関連:
jsonb_array_elements()
でネストを解除します。 ( unnest()
はPostgres配列型にのみ有効です。実際に一致するオブジェクトのみに関心があるため、すぐに結合条件でフィルタリングします。
関連:
'count'
_対象となるオブジェクトが抽出された後は、単純に_obj.val->>'count'
_です。