回答:
正規化されたスキーマに値を格納する方がはるかに効率的です。つまり、現在の設定で動作させることもできます。
このテーブル定義を仮定すると:
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は、最初に適格オブジェクトを含む行のみを処理します。たいした小さなテーブルと、なりません巨大な大きなテーブルとわずか数条件を満たす行との違いを。
関連:
とのネストを解除しjsonb_array_elements()
ます。(unnest()
Postgres配列型にのみ有効です。)実際に一致するオブジェクトのみに関心があるため、すぐに結合条件でフィルタリングします。
関連:
'count'
適格なオブジェクトが抽出された後、単に:obj.val->>'count'
。
JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)
それobj(value)
はテーブルと列のエイリアスですか?この例でobj
は、テーブルエイリアスの場合、それは何のエイリアスですか?セットから返されましたかjsonb_array_elements
?
JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'
は、同じ効果がありました(selectステートメントを更新して、のvalue
代わりに使用した場合val
)。それが表示されますjsonb_array_elements(t.usr)
1つの列のみを持つテーブルを返します。postgresは賢くobj ->>
、それと同じことを実現していobj.val ->>
ますか?
obj(value)
から来たのですか?それは上にあるLATERAL JOIN
、jsonb_array_elements
または他のどこか?