web-dev-qa-db-ja.com

PostgresのJSONオブジェクトに要素を追加する

データベース(postgres 9.2.1)にjson blobが含まれているテキストフィールドがあります。すべてが1行にあることを除いて、これは次のように見えます。明らかに:

{
  "keyword": {
    "checked": "1",
    "label": "Keyword"
  },
  "agency_name": {
    "checked": "0",
    "label": "Agency Name"
  }
}

次のように要素をjson配列に追加する必要があります。

{
  "keyword": {
    "checked": "1",
    "label": "Keyword"
  },
  "something_new": {
    "checked": "1",
    "label": "Something New"
  },
  "agency_name": {
    "checked": "0",
    "label": "Agency Name"
  }
}

新しい配列要素の配置についてはそれほど心配していません。 agency_nameの後にある可能性があります。 postgresでこれを行う簡単な方法はありますか?

19
thepriebe

同じ問題があったとしても、jsonb []に動的に新しい要素を追加したかったのです。

Column_jsonb [] = [{"name": "xyz"、 "age": "12"}]と仮定します

UPDATE table_name
   SET column_jsonb[] = array_append(column_jsonb[],'{"name":"abc","age":"22"}');

結果:[{"name": "xyz"、 "age": "12"}、{"name": "abc"、 "age": "22"}]

6
Dhruvil Thaker

PG9.5.1にアップグレードする場合、SQL操作||を使用してjsonbをマージできます。例

select '{"a":1}'::jsonb || '{"a":2, "b":2}'::jsonb

{"a": 2, "b": 2}が返されます

Pg9.5.1にアップグレードできない場合は、私見で、コード内でジョブを実行することをお勧めします。古いjsonb文字列をマップとして解析し、マップを更新してから、文字列に変換してdb-recordを更新できます。

14
NewBee

使用する || jsonbをマージして値を設定します

例:

原点:

テーブルa内:

id |情報

1 | {"aa": "bb"}

2 | {"aa": "cc"}

実行後:

update a set info = info::jsonb || ('{"id":}' || id || '}' )::jsonb 

生成する:

id |情報

1 | {"aa": "bb"、 "id":1}

2 | {"aa": "cc"、 "id":2}

something_else:

  1. 使用する -‘key’ jsonbの要素を削除します
  2. 2つのjsonbに同じキーがある場合、マージはOrigin 1を置き換えます
6
pumpkindle

PostgreSQLには、JSONサポート関数の機能はまだあまりありません。私が見ることができるのはarray_to_jsonは、元のJSONを配列に変換する対応する方法があった場合に役立ちます。配列を操作して、JSONに変換する前に、追加の要素を追加できます。

おそらく最良のことは、PL言語を使用してJSONを操作することです。明らかなのは、PostgreSQLでJavaScriptプログラミング機能を提供するPLV8です。 JavaScriptでユーザー定義関数を記述し、それに応じてJSONブロブを操作します。

もちろん、Javaのような他の多くのPL言語、PythonまたはPerlは、JSONデータの操作と同じくらい優れている場合があり、システムへのインストールが簡単になる可能性があります。ユーザー定義関数は、あなたがそれらを設定している場合、これらのそれぞれ。

5
Edmund

バージョン9.5では、create-missing = TRUEを指定した jsonb_set 関数が提供されています。その他の場合は、次のハックを使用して情報を追加します。

SELECT (trim( trailing '}' from data::text) || ', "c":2}')::json

より正しい方法で新しい値を追加/置換するには:

UPDATE t
SET data=t3.data

FROM t AS t1
INNER JOIN
(
  SELECT id, json_object_agg(t.k,t.v)
  FROM
    (
      SELECT *
      FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2
      WHERE t.k != 'c'

      UNION ALL
      SELECT id, 'c'::text as k, '"new value"'::json as v FROM t1
    ) as t3
  GROUP by id
) as t4 ON (t1.id=t4.id)

キーを削除するには:

UPDATE t
SET data=t3.data

FROM t AS t1
INNER JOIN
(
  SELECT id, json_object_agg(t.k,t.v)
  FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2
  WHERE t.k != 'c'
  GROUP by id
) as t4 ON (t1.id=t4.id)
2

私はまさにこの問題を抱えていました。この解決策はかなり「純粋な」オブジェクト操作であり、私は一種の「sql」関数をplpgsqlよりも優先しています。主なことは、json_eachを使用して分解し、レコードを提供してから、レコードを作成することです

CREATE OR REPLACE FUNCTION json_extend_object(
    input_object json,
    append_key text,
    append_object json)
  RETURNS json AS
$BODY$
    select json_object_agg (((json_val)::record).key, ((json_val)::record).value)
    from (
        select json_val 
        from (select json_each (input_object) as json_val) disaggr
        where ((json_val::record).key != append_key)
        union 
        select newvals
        from (
            select append_key, append_object
        ) newvals
    ) to_rows;
$BODY$
  LANGUAGE sql IMMUTABLE
  ;
1
Andrew Wolfe

Andrew Wolfeが提供するソリューションは優れていますが、postgresバージョン<9.4とは互換性がありません。また、9.4以降のバージョンを使用している場合は、jsonbを使用し、|| (連結)演算子を使用して要素をjsonに追加します。

したがって、json_extend_objectの9.3互換バージョンは次のとおりです。

CREATE OR REPLACE FUNCTION json_extend_object( input_object json, append_key text, append_object json) RETURNS json AS $BODY$ select ('{'||string_agg(''||to_json((json_val::record).key)||':'|| to_json((json_val::record).value), ',')||'}')::json from ( select json_val from (select json_each (input_object) as json_val) jsonvals where ((json_val::record).key != append_key) union select newvals from (select append_key, append_object) newvals ) to_rows; $BODY$ LANGUAGE sql IMMUTABLE;

0
clancien