You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用运算符提取仅含单个键的JSONB对象的键(替代表函数jsonb_each)

如何用运算符提取仅含单个键的JSONB对象的键(替代表函数jsonb_each)

嘿,我完全懂你觉得用jsonb_each这种表函数处理单键JSONB对象有多啰嗦——就像拿大象拍苍蝇,完全没必要!下面给你几个更清爽的方法来提取那个唯一的键,还能直接用到你的函数里大幅简化代码~

核心提取方法(替代表函数)

针对仅含单个键的JSONB对象,你可以用以下两种简洁方式提取键,完全不用依赖jsonb_each这类表函数:

方法1:标量子查询提取键

利用jsonb_object_keys的标量返回特性,PostgreSQL会自动将单结果子查询作为标量值返回:

(SELECT key FROM jsonb_object_keys(你的单键JSONB对象))

对应的提取该键的值,用你之前想到的路径运算符就可以:

你的单键JSONB对象 #>> '{$.*}'

{$.*}会匹配对象的所有值,因为只有一个键,所以直接返回对应的值。

方法2:JSON路径查询(PostgreSQL 12+支持)

用JSON路径语法直接获取唯一键,写法更紧凑:

jsonb_path_query_first(你的单键JSONB对象, 'keys($)') #>> '{}'
  • keys($)会返回对象的所有键组成的JSON数组
  • jsonb_path_query_first取数组的第一个(也是唯一一个)元素
  • #>> '{}'将JSONB类型的键转换为普通文本

简化你的jreduxseq_to_text函数

基于上面的方法,我们可以完全删掉原来那堆繁琐的LATERAL+UNION代码,让函数逻辑更清晰:

CREATE or replace FUNCTION jreduxseq_to_text(
  p_list jsonb,
  p_level int default 1,
  p_max_level int default 3
) RETURNS TABLE(
  level integer,
  ordinality bigint,
  prefix text,
  suffixes jsonb,
  is_prefix boolean
) AS $f$
SELECT
  p_level,
  t.ordinality,
  CASE
    WHEN t.is_prefix THEN (SELECT key FROM jsonb_object_keys(t.value))
    ELSE t.value #>> '{}'
  END as prefix,
  CASE
    WHEN t.is_prefix THEN t.value #>> '{$.*}'::text[]
    ELSE NULL
  END as suffixes,
  t.is_prefix
FROM (
  SELECT
    ordinality,
    value,
    jsonb_typeof(value)='object' AS is_prefix
  FROM jsonb_array_elements(p_list) WITH ORDINALITY
) t
$f$ LANGUAGE SQL IMMUTABLE;

简化说明

  1. 当元素是单键JSONB对象(t.is_prefix = true):
    • 用标量子查询(SELECT key FROM jsonb_object_keys(t.value))直接提取唯一键作为prefix
    • #>> '{$.*}'提取该键对应的JSONB值作为suffixes
  2. 当元素是普通字符串时,逻辑和原来保持一致
  3. 彻底移除了原来需要处理空对象、UNION拼接的冗余代码,结构清爽很多

你可以测试一下这个简化后的函数,和原函数的输出结果完全一致,但是代码复杂度直接降了一个等级,再也不用为了取一个键写一堆表函数逻辑啦!

火山引擎 最新活动