使用Postgres中的计算数据结构更新JSONB字段

时间:2016-11-04 14:35:28

标签: sql postgresql

我想将兄弟记录中的一些数据聚合到一个jsonb字段中。

以下是一个示例数据结构,与我正在使用的数据结构非常相似:

CREATE TABLE so.a (
  id integer,
  foo integer,
  bar integer,
  -- a lot of other data
  CONSTRAINT a_pkey PRIMARY KEY (id)
);

CREATE TABLE so.b (
  id integer,
  a1 integer,
  a2 integer,
  data jsonb,
  CONSTRAINT b_pkey PRIMARY KEY (id),
  CONSTRAINT "a1_fkey" FOREIGN KEY (a1) REFERENCES so.a (id),
  CONSTRAINT "a2_fkey" FOREIGN KEY (a2) REFERENCES so.a (id)
);

和一些示例数据集:

INSERT INTO so.a VALUES
  (1, 42, 24),
  (2, 22, 33),
  (3, 66, 99);

INSERT INTO so.b VALUES
  (1, 1, 2, NULL),
  (2, 2, 3, NULL),
  (3, 3, 1, NULL);

现在,我想在b.data行填充来自兄弟记录a1a2的数据:

data = [{
  "foo": a1.foo,
  "bar": a1.bar
}, {
  "foo": a2.foo,
  "bar": a2.bar
}]

我提出的最佳解决方案是首先使用json函数和字符串连接运算符to_json构建||字符串,然后再将其转换为jsonb:< / p>

UPDATE
  so.b
SET
  data = ('[{
    "foo": ' || to_json(t1.foo) || ',
    "bar": ' || to_json(t1.bar) || '
  }, {
    "foo": ' || to_json(t2.foo) || ',
    "bar": ' || to_json(t2.bar) || '
  }]')::jsonb
FROM
  so.a t1,
  so.a t2
WHERE 
  t1.id = b.a1 AND
  t2.id = b.a2;

此解决方案非常有效:

SELECT id, data FROM so.b;
-- 1, [{"bar": 24, "foo": 42}, {"bar": 33, "foo": 22}]
-- 2, [{"bar": 33, "foo": 22}, {"bar": 99, "foo": 66}]
-- 3, [{"bar": 99, "foo": 66}, {"bar": 24, "foo": 42}]

但对我来说似乎太笨拙了。

所以我想知道,也许有更好的方法来实现我想要的目标。

UPD。:如果我还要描述我之前解决此问题的尝试,我认为这可能会有所帮助。

我想保持简单,所以我尝试使用array_to_json功能:

SET
  data = array_to_json(ARRAY[t1, t2])

但我的数据库中有很多过多的数据。由于我无法找到限制t1t2字段的方法,因此我放弃了这种方法。

1 个答案:

答案 0 :(得分:1)

我认为你唯一能做的就是使用jsonb_build_*函数而不是字符串连接。我:

UPDATE so.b SET 
    data = jsonb_build_array( 
        jsonb_build_object( 
            'foo', to_json(t1.foo), 
            'bar', to_json(t1.bar) 
        ), 
        jsonb_build_object( 
            'foo', to_json(t2.foo), 
            'bar', to_json(t2.bar) 
        ) 
    ) 
FROM 
    so.a t1, so.a t2 
WHERE 
    t1.id = b.a1 AND t2.id = b.a2;