Postgresql中JSONB数据类型修改

JSONB Data Type Modification in Postgresql

我对在 postgres 中修改 jsonb 数据类型有疑问

基本设置:-

数组=> ["1", "2", "3"]
现在我有一个带有 id 列和 jsonb 数据类型 列的 postgresql 数据库,我们只说 cards.

  id    cards
-----+---------
1       {"1": 3, "4": 2}

这就是 table 中名为 test

的数据

问题:

如何将 id->1 的卡片从 {"1": 3, "4": 2} 转换为 {"1": 4, "4":2, "2": 1, "3": 1}

我希望如何发生变化:

array 开始,将 cards jsonb 中作为键存在的数组中存在的所有元素递增 1,从而将 {"1": 3} 更改为 {"1": 4 } 并将不存在的值作为键插入 cards jsonb 中,值为 1 从而将 {"1":4, "4":2} 更改为 {"1": 4, "4":2, "2":1, "3":1} 纯粹通过 postgres.

部分解决方案

我就我的问题向一位前辈寻求支持,我被告知:-

Roughly (names may differ): object keys to explode cards, array_elements to explode the array, left join them, do the calculation, re-aggregate the object. There may be a more direct way to do this but the above brute-force approach will work.

SELECT jsonb_each_text(tester_cards) AS each_text, jsonb_array_elements_text('[["1", 1], ["2", 1], ["3", 1]]') AS array_elements FROM tester WHERE id=1;

TLDR;

现在看起来我好像在要求被喂食,但我真的还没有设法找到解决它的方法,因此非常感谢任何帮助

关键的见解是,使用 jsonb_eachjsonb_object_agg 您可以 round-trip 子查询中的 JSON 对象:

SELECT id, (
  SELECT jsonb_object_agg(key, value)
  FROM jsonb_each(cards)
) AS result
FROM test;

(online demo)

现在您可以 JOIN 这些 key-value 对与数组输入的 jsonb_array_elements 对。你的同事很接近,但不太正确:它需要一个完整的外部连接,而不仅仅是一个左(或右)连接来为你的输出获取所有需要的对象键,除非你的输入之一是另一个输入的子集。

SELECT id, (
  SELECT jsonb_object_agg(COALESCE(obj_key, arr_value), …)
  FROM jsonb_array_elements_text('["1", "2", "3"]') AS arr(arr_value)
  FULL OUTER JOIN jsonb_each(cards) AS obj(obj_key, obj_value) ON obj_key = arr_value
) AS result
FROM test;

(online demo)

现在剩下的只是实际计算和转换为 UPDATE 语句:

UPDATE test
SET cards = (
  SELECT jsonb_object_agg(
    COALESCE(key, arr_value),
    COALESCE(obj_value::int, 0) + (arr_value IS NOT NULL)::int
  )
  FROM jsonb_array_elements_text('["1", "2", "3"]') AS arr(arr_value)
  FULL OUTER JOIN jsonb_each_text(cards) AS obj(key, obj_value) ON key = arr_value
);

(online demo)