2

我想设计一个查询,我可以在其中以受控方式将两个 jsonb 与 postgreSQL 中未知数量/组的元素组合在一起。jsonb 运算符||几乎完全符合我的目的,但是对于其中一个 jsonb 元素,我想用逗号连接和分隔这两个值,而不是让第二个 jsonb 的值覆盖第一个值。例如:

'{"a":"foo", "b":"one", "special":"comma"}'::jsonb || '{"a":"bar", "special":"separated"}'::jsonb → '{"a":"bar", "b":"one", "special":"comma,separated"}'

我当前的查询如下:

INSERT INTO table AS t (col1, col2, col3_jsonb)
VALUES ("first", "second", '["a":"bar", "special":"separated"]'::jsonb))
ON CONFLICT ON CONSTRAINT unique_entries DO UPDATE
SET col3_jsonb = excluded.col3_jsonb || t.col3_jsonb
RETURNING id;

这导致 jsonb 元素col3_jsonb的值 special 设置为separated而不是 desired comma,separated。我知道这是按照文档说明工作的连接运算符,但我不确定如何以不同的方式处理 jsonb 的一个元素,而不是尝试WITH..在查询中的其他地方使用子句提取特殊值。任何见解或提示将不胜感激!

4

2 回答 2

1

您可以使用jsonb_each两个值,然后jsonb_object_agg将它们放回对象中:

…
SET col3_jsonb = (
 SELECT jsonb_object_agg(
    key,
    COALESCE(to_jsonb((old.value->>0) || ',' || (new.value->>0)), new.value, old.value)
  )
  FROM jsonb_each(example.old_obj) old
  FULL OUTER JOIN jsonb_each(example.new_obj) new USING (key)
)

在线演示

将任意 JSON 值转换为可连接字符串需要一个技巧。如果你知道你所有的对象属性都有字符串值,你可以通过使用jsonb_each_text来简化:

  SELECT jsonb_object_agg(
    key,
    COALESCE(old.value || ',' || new.value, new.value, old.value)
  )
  FROM jsonb_each_text(example.old_obj) old
  FULL OUTER JOIN jsonb_each_text(example.new_obj) new USING (key)
于 2021-06-09T21:47:33.477 回答
1
with t(a,b) as (values(
    '{"a":"foo", "b":"one", "special":"comma"}'::jsonb,
    '{"a":"bar", "special":"separated"}'::jsonb))
select
    a || jsonb_set(b, '{special}',
        to_jsonb(concat_ws(',', nullif(a->>'special', ''), nullif(b->>'special', ''))))
from t;
┌────────────────────────────────────────────────────────┐
│                        ?column?                        │
├────────────────────────────────────────────────────────┤
│ {"a": "bar", "b": "one", "special": "comma,separated"} │
└────────────────────────────────────────────────────────┘

nullif()以及缺少一个或两个值/空/空concat_ws()的情况所需的功能"special"

于 2021-06-09T22:50:04.383 回答