我有一个嵌套JSON数组的jsonb
值,需要删除一个元素:
{"values": ["11", "22", "33"]}
jsonb_set(column_name, '{values}', ((column_name -> 'values') - '33')) -- WORKS!
我也有一个类似的jsonb
值,带有numbers,而不是字符串:
{"values": [11, 22, 33]}
jsonb_set(column_name, '{values}', ((column_name -> 'values') - 33)) -- FAILS!
在这种情况下,33
被用作数组的索引。
如何从JSON数组中删除数字项?
3条答案
按热度按时间30byixjq1#
两个论断:
1.许多Postgres JSON函数和操作符都以键/值对中的键为目标。JSON数组中的字符串(
"abc"
或"33"
)被视为没有值的键。但数字(33
或123.45
)数组元素被视为 * 值 *。1.
-
运算符目前有三种变体。其中两种适用于这里。正如最近澄清的手册所描述的(currently /devel):操作员
说明
实施例
:————————————————————-
jsonb
-
text
→jsonb
从JSON对象中删除键(及其值),或从JSON数组中删除匹配的字符串值。
'{"a": "b", "c": "d"}'::jsonb - 'a'
→{"c": "d"}
'["a", "b", "c", "b"]'::jsonb - 'b'
→["a", "c"]
...
jsonb
-
integer
→jsonb
删除具有指定索引的数组元素(负整数从末尾开始计数)。
如果JSON值不是数组,则抛出错误。
'["a", "b"]'::jsonb - 1
→["a"]
如果右操作数是一个数字字面值,Postgres operator type resolution将得到后面的变体。
不幸的是,由于Assert1,我们不能使用前一个变体。
所以我们必须使用一个workaround像:
不要将非嵌套元素转换为
integer
(就像另一个答案建议的那样)。integer
。numeric
,但其他数组元素可能是string
等。所以这适用于 any 类型,而不仅仅是integer(JSON numeric)。例如:
r6l8ljro2#
不幸的是,Postgres json运算符
-
只支持字符串值,如explained in the documentation:操作数:
-
右操作数类型:
text
产品描述:从左操作数中删除键/值对或字符串元素。键/值对根据其键值进行匹配。
另一方面,如果你传递一个整数值作为右操作数,Postgres会认为它是需要删除的数组元素的 index。
另一种选择是使用
jsonb_array_elements()
和横向连接取消嵌套数组,过滤掉不需要的值,然后重新聚合:Demo on DB Fiddle:
wgx48brx3#
PostgreSQL 12+
从这个版本开始,它具有强大的功能,可以使用
jsonpath
语法与JSONB一起工作。有一个很棒的article由该功能的作者编写,它比官方文档更好地描述了所有用例。jsonb_path_query_array
获取除
33
以外的所有数组项:通过
jsonb_set
的组合,它给出了我们想要的: