JSON型内の配列要素のクエリ


118

jsonPostgreSQL 9.3で型をテストしようとしています。という表にと呼ばれる列
がありjsonます。JSONは次のようになります。datareports

{
  "objects": [
    {"src":"foo.png"},
    {"src":"bar.png"}
  ],
  "background":"background.png"
}

'objects'配列の 'src'値に一致するすべてのレポートのテーブルをクエリしたいと思います。たとえば、一致するすべてのレポートについてDBにクエリを実行することはできます'src' = 'foo.png'か?に一致するクエリを正常に作成しました"background"

SELECT data AS data FROM reports where data->>'background' = 'background.png'

しかし、"objects"値の配列があるので、私はうまくいくものを書くことができないようです。一致するすべてのレポートについてDBをクエリすることはできます'src' = 'foo.png'か?私はこれらのソースを調べましたが、それでもまだ取得できません。

私もこのようなことを試しましたが、役に立ちませんでした:

SELECT json_array_elements(data->'objects') AS data from reports
WHERE  data->>'src' = 'foo.png';

私はSQLのエキスパートではないので、何が問題なのかわかりません。

回答:


214

json Postgres 9.3以降

句のjson_array_elements()ラテラル結合の関数を使用してJSON配列のネストを解除し、FROMその要素をテストします。

WITH reports(data) AS (
   VALUES ('{"objects":[{"src":"foo.png"}, {"src":"bar.png"}]
           , "background":"background.png"}'::json)
   ) 
SELECT *
FROM   reports r, json_array_elements(r.data#>'{objects}') obj
WHERE  obj->>'src' = 'foo.png';

CTEWITHクエリ)は、単にテーブルを置換しますreports
または、単一レベルのネストと同等:

SELECT *
FROM   reports r, json_array_elements(r.data->'objects') obj
WHERE  obj->>'src' = 'foo.png';

->>->および#>演算子はマニュアルで説明されています。

どちらのクエリも暗黙的なを使用しJOIN LATERALます。

SQL Fiddle。

密接に関連する答え:

jsonb Postgres 9.4以降

同等のものを使用してくださいjsonb_array_elements()

さらに良いのは、新しい「contains」演算子を使用することです@>(式の一致するGINインデックスと組み合わせるのが最適ですdata->'objects')。

CREATE INDEX reports_data_gin_idx ON reports
USING gin ((data->'objects') jsonb_path_ops);

SELECT * FROM reports WHERE data->'objects' @> '[{"src":"foo.png"}]';

キーにobjectsはJSON 配列が含まれているため、検索語句の構造と一致させ、配列要素も角括弧で囲む必要があります。単純なレコードを検索するときは、配列の角かっこを削除します。

詳細な説明とその他のオプション:


1
@pacothelovetaco:jsonb/ pg 9.4のアップデートを追加。余談ですが、単純なケース(1レベルのネスト)の場合、->オペレーターはjson9.3ページのトリックも行います。
Erwin Brandstetter、2015年

1
@ pacothelovetaco、9.3ページでは、「#>」は秘密のソースではありません。「->」はjson objecも返すため、ケースには問題ありません。'#>'は、 '{}'でパスを簡単に指定できるので、ネストされたjsonパスの場合に役立ちます
Gob00st

1
@> '[{"src": "foo.png"}]'; where条件で正常に動作しますが、このように特定のオブジェクトを削除するにはどうすればよいですか?このオブジェクトのインデックスがわかりません。キー値で削除したい。
Pranay Soni

1
@PranaySoni:として新しい質問お問い合わせください質問を。コメントは場所ではありません。あなたはいつでもコンテキストのためにこれにリンクすることができます。
Erwin Brandstetter 2016

@ErwinBrandstetterさん、両方のドキュメントを部分一致で見つけることは可能ですか?たとえば、「[{"src": "
。png

8

json型の列を持つテーブルを作成する

CREATE TABLE friends ( id serial primary key, data jsonb);

jsonデータを挿入しましょう

INSERT INTO friends(data) VALUES ('{"name": "Arya", "work": ["Improvements", "Office"], "available": true}');
INSERT INTO friends(data) VALUES ('{"name": "Tim Cook", "work": ["Cook", "ceo", "Play"], "uses": ["baseball", "laptop"], "available": false}');

次に、データをフェッチするためのクエリをいくつか作成しましょう

select data->'name' from friends;
select data->'name' as name, data->'work' as work from friends;

結果に逆コンマ( ")と角括弧([])が付いていることに気づいたかもしれません

    name    |            work            
------------+----------------------------
 "Arya"     | ["Improvements", "Office"]
 "Tim Cook" | ["Cook", "ceo", "Play"]
(2 rows)

値だけを取得するには、次を使用します ->>

select data->>'name' as name, data->'work'->>0 as work from friends;
select data->>'name' as name, data->'work'->>0 as work from friends where data->>'name'='Arya';

22
これは、質問にはっきりと接続されていない、心地よいフォーマットのノイズです。
Erwin Brandstetter

4
これは重宝しました。jsonbで配列にドリルする方法を示します
GavinBelson

0

テーブルからSRCとしてdata-> 'objects'-> 0-> 'src'を選択しますdata-> 'objects'-> 0-> 'src' = 'foo.png'


2
あなたは0であった。インデックス、知っている場合にのみ、このでは有用であろう
BuyutジョコRivai

はい、しかし行ごとにマップする配列オブジェクトを分解する方法があり、それを使用できます。私が間違っている場合は私を修正してください。
anand shukla

ない良い解決策は、あなたが確認することができないとして、「SRC」は位置0にあり
simUser
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.