2017-06-01 53 views
2

私はバージョン9.6を使用しています。私はこのように書類を持っている:PostgreSQLでJSON配列要素を選択して更新するにはどうすればよいですか?

{ 
    "name" : "John Doe", 
    "phones" : [ 
     { 
      "type" : "mobile", 
      "number" : "555-555-0000", 
      "deleted": false 
     }, 
     { 
      "type" : "home", 
      "number" : "555-555-0001", 
      "needsUpdated" : true 
     }, 
     { 
      "type" : "work", 
      "number" : "555-555-0002" 
     } 
    ] 
} 

私はこのようにそれらを作成しました:今、私は名前ジョン・ドウと行を選択する方法にA、を把握しようとしている

create table t_json (c_json json not null); 

insert into t_json (c_json) values ('{"name":"John Doe","phones": [{"type":"mobile","number":"555-555-0000"},{"type":"home","number":"555-555-0001"},{"type": "work","number": "555-555-0002"}]}'); 

insert into t_json (c_json) values ('{"name":"Jane Dane","phones": [{"type":"mobile","number":"555-555-0030"},{"type":"home","number":"555-555-0020"},{"type": "work","number": "555-555-0010"}]}'); 

彼の携帯電話番号を「555-555-0003」に更新します。

私はこのような適切な文書を照会できることを考え出しPostgresql 9.6 documentationここから:

select c_json from t_json where c_json->>'name' = 'John Doe'; 

しかし、私はタイプによって電話・アレイ内の適切なサブ文書を選択する方法を確認するために失敗しています、数値を更新します。誰か助けてくれますか?

EDIT私は余分な値を持っており、一貫していないサブ文書を想定する必要が

。そこで私は上記をいくつか追加しました。この時点でデータの損失がない限り、このアップデートは不可能であると私は確信しています。

+0

のように私はあなたが[この – maxymoo

+0

可能な複製のためにjsonb_set使うと思いますが、あります。新しいPostgreSQL JSONデータ型内のフィールドを変更する方法は?](https://stackoverflow.com/questions/18209625/how-do-i-modify-fields-inside-the-new-postgresql-json-datatype) –

+0

@ JorgeCamposはこれが重複していません。私はその質問全体とすべての答えを読んで、配列内のサブ文書を更新する方法を見つけませんでした。しかし、ありがとう。 –

答えて

1

電話機アレイでタイプ別に適切なサブ文書を選択するにはどうすればよいですか?

電話番号を取得する場合は、これを使用します。

SELECT * FROM t_json 
    WHERE (c_json -> 'phones')::JSONB @> 
     '[{"type":"mobile","number":"555-555-0000"}]'::JSONB; 

数値を更新する方法:?文書を対応することで、電話番号で検索したい場合は、この作品https://www.postgresql.org/docs/9.6/static/queries-table-expressions.html#QUERIES-LATERAL

SELECT c_json ->> 'name', phones.type, phones.number 
    FROM t_json 
    CROSS JOIN json_to_recordset(c_json -> 'phones') 
     AS phones("type" TEXT, "number" TEXT); 

ですか

コメントで述べたように、同様の質問があり、How do I modify fields inside the new PostgreSQL JSON datatype?

これを行うための他の方法が

UPDATE t_json SET c_json = newvalue FROM (
    SELECT to_json(updated) AS newvalue FROM (
     SELECT c_json ->> 'name' as "name", 
      json_agg(json_build_object('type', phones.type, 'number', 
       CASE phones.type WHEN 'mobile' THEN '555-555-0003' ELSE phones.number END) 
      ) AS phones 
    FROM t_json 
    CROSS JOIN json_to_recordset(c_json -> 'phones') 
     AS phones("type" TEXT, "number" TEXT) 
    WHERE c_json->>'name' = 'John Doe' 
    GROUP BY name 
    ) as updated 
) AS sub WHERE c_json ->> 'name' = 'John Doe'; 
+0

うわー、印象的な答え!私に見るものを与えてくれてありがとう。この質問は重複ではなく、配列内のサブ文書を更新する方法を具体的に求めています。コメント全体でその質問全体を読んだことがあります。コードスニペットが実際にjsonオブジェクト全体を取得し、変更して元に戻すように見えますが、それは正しいのですか?これは酸に準拠していますか? –

+0

はい、JSONオブジェクト全体を展開して再構成します。 1つのSQLステートメント内では、もちろんACIDに準拠しています。 – crvv

+0

私はそう思っていましたが、私は仮定したくありません:)あなたはjson_aggでサブ文書を再作成していますか?そのサブドキュメントに「更新済み」などの追加のキー:値のペアがある場合はどうなりますか。その余分なデータは、あなたが文に追加しない限り失われますか?または私は正しく理解していないのですか? –

関連する問題