データベース(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でこれを行う簡単な方法はありますか?
同じ問題があったとしても、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"}]
PG9.5.1にアップグレードする場合、SQL操作||
を使用してjsonbをマージできます。例
select '{"a":1}'::jsonb || '{"a":2, "b":2}'::jsonb
{"a": 2, "b": 2}
が返されます
Pg9.5.1にアップグレードできない場合は、私見で、コード内でジョブを実行することをお勧めします。古いjsonb文字列をマップとして解析し、マップを更新してから、文字列に変換してdb-recordを更新できます。
使用する ||
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:
-
‘key’
jsonbの要素を削除しますPostgreSQLには、JSONサポート関数の機能はまだあまりありません。私が見ることができるのはarray_to_json
は、元のJSONを配列に変換する対応する方法があった場合に役立ちます。配列を操作して、JSONに変換する前に、追加の要素を追加できます。
おそらく最良のことは、PL言語を使用してJSONを操作することです。明らかなのは、PostgreSQLでJavaScriptプログラミング機能を提供するPLV8です。 JavaScriptでユーザー定義関数を記述し、それに応じてJSONブロブを操作します。
もちろん、Javaのような他の多くのPL言語、PythonまたはPerlは、JSONデータの操作と同じくらい優れている場合があり、システムへのインストールが簡単になる可能性があります。ユーザー定義関数は、あなたがそれらを設定している場合、これらのそれぞれ。
バージョン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)
私はまさにこの問題を抱えていました。この解決策はかなり「純粋な」オブジェクト操作であり、私は一種の「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
;
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;