如何使用PostgreSQL JSONB_SET()创建新的深层对象元素

时间:2017-10-17 19:04:25

标签: postgresql jsonb postgresql-9.6

我必须遗漏某些内容......似乎JSONB_SET()无效advertised

SELECT JSONB_SET(
    '{"k1": {"value": "v1"}}',
    '{k2,value}',
    '"v2"',
    TRUE
);

结果:

----+------------------------
    | jsonb_set
    | jsonb
----+------------------------
  1 | {"k1": {"value": "v1"}}
----+------------------------

我期待{"k1": {"value": "v1"}, "k2": {"value": "v2"}} 我还尝试FALSE作为第四个参数,以防它被颠倒或者什么。

我正在使用PostgreSQL 9.6.4

2 个答案:

答案 0 :(得分:3)

该文件说:

  

jsonb_set(目标jsonb,路径文本[],new_value jsonb [,create_missing   布尔])

在您的示例中,第二个参数 - '{k2,value}'是搜索路径,但由于第一个路径为k2且不存在,因此之前的结果为 {{可以添加/替换1}}。

简单来说 - jsonb_set不是按照您尝试使用搜索路径的方式构建整个JSON文档,而是添加或替换单个键/值。

如果你想添加/替换全新的JSON集,你可以使用value(concatenate)运算符来代替:

||

您可以改为使用-- Add example: SELECT $${"k1": {"value": "v1"}}$$::jsonb || $${ "k2": { "value": "v2"}}$$::jsonb; ?column? ------------------------------------------------ {"k1": {"value": "v1"}, "k2": {"value": "v2"}} (1 row) -- Replace example SELECT $${"k1": {"value": "v1"}}$$::jsonb || $${ "k1": { "value": "v2"}}$$::jsonb; ?column? ------------------------- {"k1": {"value": "v2"}} (1 row) 代替:

jsonb_set()

答案 1 :(得分:1)

我只是遇到了同样的问题,并为此创建了一个简单的postgres函数。 可能不是最快的解决方案,对于深插来说可能特别慢,但到目前为止对我来说还不错!

CREATE OR REPLACE FUNCTION jsonb_deep_set(curjson jsonb, globalpath text[], newval jsonb) RETURNS jsonb AS
$$
  BEGIN
    IF curjson is null THEN
      curjson := '{}'::jsonb;
    END IF;
    FOR index IN 1..ARRAY_LENGTH(globalpath, 1) LOOP
      IF curjson #> globalpath[1:index] is null THEN
        curjson := jsonb_set(curjson, globalpath[1:index], '{}');
      END IF;
    END LOOP;
    curjson := jsonb_set(curjson, globalpath, newval);
    RETURN curjson;
  END;
$$
LANGUAGE 'plpgsql';

jsonb代替json使其也适用于json对象。