PostgreSQLでのJSONデータ型の使用に関する問題に直面しています。 JavaモデルをDBに非正規化して保存しようとしました。モデルは複雑なオブジェクトのリストを備えているため、ネイティブPostgreSQL配列でJSONとしてモデル化することにしました。
これは私のテーブル作成ステートメントの抜粋です:
CREATE TABLE test.persons
(
id UUID,
firstName TEXT,
lastName TEXT,
communicationData JSON[],
CONSTRAINT pk_person PRIMARY KEY (id)
);
ご覧のとおり、それはJSONで通信データオブジェクトのリストを備えた人物です。そのようなオブジェクトの1つは次のようになります。
{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf6"}
PostgreSQLのarray_appendを使用して、このようなJSONオブジェクトを配列に簡単に追加できます。ただし、既知の値をアレイから削除できません。 f.e.このSQLステートメント:
UPDATE test.persons
SET communicationData = array_remove(
communicationData,
'{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf6"}'::JSON
)
WHERE id = 'f671eb6a-d603-11e3-bf6f-07ba007d953d';
これはERROR: could not identify an equality operator for type json
で失敗します。 JSON配列から既知の値を削除する方法についてのヒントはありますか?また、配列内の位置によって削除することもできます。
PostgreSQLのバージョンは9.3.4です。
jsonb
jsonb
data type in Postgres 9.4-'b' for 'binary'について考えます。特に、jsonb
の 等価演算子_=
_があります があります。ほとんどの人は切り替えたくなるでしょう。
json
データ型 json
に定義されている_=
_演算子はありません。これは、json
値全体の同等性を確立するための明確に定義された方法がないためです。ただし、以下を参照してください。
あなたはcouldをtext
にキャストし、次に_=
_演算子を使用します。これは短いですが、テキスト表現がたまたま一致する場合にのみ機能します。コーナーケースを除いて、本質的に信頼できません。見る:
または、 unnest
配列にして、 _->>
_ operator to .. _get JSON object field as text
_を使用して比較できます個々のフィールド。
2行:最初の質問のようなもの、2番目の行は単純な値。
_CREATE TABLE tbl (
tbl_id int PRIMARY KEY
, jar json[]
);
INSERT INTO t VALUES
(1, '{"{\"value\" : \"03334/254146\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f5\"}"
,"{\"value\" : \"03334/254147\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f6\"}"
,"{\"value\" : \"03334/254148\", \"typeId\" : \"ea4e7d7e-7b87-4628-ba50-f7\"}"}')
, (2, '{"{\"value\" : \"a\", \"typeId\" : \"x\"}"
,"{\"value\" : \"b\", \"typeId\" : \"y\"}"
,"{\"value\" : \"c\", \"typeId\" : \"z\"}"}');
_
デモ1:あなたcouldtext
表現でarray_remove()
を使用します(信頼できません)。
_SELECT tbl_id
, jar, array_length(jar, 1) AS jar_len
, jar::text[] AS t, array_length(jar::text[], 1) AS t_len
, array_remove(jar::text[], '{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-f6"}'::text) AS t_result
, array_remove(jar::text[], '{"value" : "03334/254147", "typeId" : "ea4e7d7e-7b87-4628-ba50-f6"}'::text)::json[] AS j_result
FROM tbl;
_
デモ2:個々の要素の配列とテストフィールドのネストを解除します。
_SELECT tbl_id, array_agg(j) AS j_new
FROM tbl, unnest(jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> '03334/254146'
AND j->>'typeId' <> 'ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf5'
GROUP BY 1;
_
デモ3:行タイプを使用した代替テスト。
_SELECT tbl_id, array_agg(j) AS j_new
FROM tbl, unnest(jar) AS j -- LATERAL JOIN
WHERE (j->>'value', j->>'typeId') NOT IN (
('03334/254146', 'ea4e7d7e-7b87-4628-ba50-6a5f6e63dbf5')
,('a', 'x')
)
GROUP BY 1;
_
UPDATE
要求通り最後に、これはUPDATE
を実装する方法です。
_UPDATE tbl t
SET jar = j.jar
FROM tbl t1
CROSS JOIN LATERAL (
SELECT ARRAY(
SELECT j
FROM unnest(t1.jar) AS j -- LATERAL JOIN
WHERE j->>'value' <> 'a'
AND j->>'typeId' <> 'x'
) AS jar
) j
WHERE t1.tbl_id = 2 -- only relevant rows
AND t1.tbl_id = t.tbl_id;
_
db <>フィドル ここ
暗黙の_LATERAL JOIN
_について:
配列のネスト解除について:
状況を単純化するために、正規化されたスキーマを検討してください。メインテーブルとn:1の関係で結合された(配列列ではなく)json
値の個別のテーブルです。