如何用jsonb_path_query()获取带根键的过滤后JSONB数据?
在PostgreSQL 13中过滤JSONB并保留根键的方法
你当前的查询能正确过滤出符合条件的子对象,但无法保留对应的根键;而尝试的路径表达式因判断逻辑错误,返回了整个原始JSON对象。以下是两种可行的解决方法:
方法1:使用jsonb_each展开后过滤再聚合
这种方法通过将顶层JSON对象拆分为键值对,过滤出符合条件的项后重新组合成JSON对象:
SELECT jsonb_object_agg(key, value) FROM jsonb_each('{ "100": { "name": "test", "priority": 5 }, "101": { "name": "test2", "priority": 10 }, "102": { "name": "test3", "priority": 15 } }'::jsonb) WHERE (value->>'priority')::integer > 10;
执行后会返回期望的结果:
{ "102": { "name": "test3", "priority": 15 } }
方法2:使用JSON路径的keyvalue()函数
如果你更倾向于用JSON路径表达式实现,可以借助keyvalue()函数将顶层对象转换为键值对数组,过滤后再聚合:
SELECT jsonb_object_agg(item.key, item.value) FROM jsonb_path_query( '{ "100": { "name": "test", "priority": 5 }, "101": { "name": "test2", "priority": 10 }, "102": { "name": "test3", "priority": 15 } }'::jsonb, '$.keyvalue() ? (@.value.priority > 10)' ) AS item;
keyvalue()会把每个顶层键值对转换为{"key": "键名", "value": 子对象}的结构,路径表达式$.keyvalue() ? (@.value.priority > 10)会筛选出子对象priority大于10的项,最后用jsonb_object_agg重新组合成目标JSON。
为什么你的尝试查询失败?
你之前的路径表达式$ ? (@.*.priority > 10)的逻辑是判断整个JSON对象是否存在任意子对象满足priority>10,只要有一个符合条件,就会返回整个原始对象,而非过滤掉不符合条件的子键值对,这就是返回全部数据的原因。
内容的提问来源于stack exchange,提问作者Shrikar Kalagi
相关产品推荐
相关产品推荐

