Ale*_*erF 5 postgresql functions json
如何从 Postgres 中的 json(b) 对象中提取/获取/选择“子对象”?
似乎有很多信息几乎可以让我到达那里,但又不完全是。很多关于转换为记录、过滤然后从中构建新对象的内容。说实话,我真的很惊讶这不是内置功能。也许有一种简单的方法可以通过组合内置 fns 来实现此目的?我正在寻找的本质上相当于select-keys;一个函数(比如jsonb_select_keys)给出了这个:
SELECT jsonb_select_keys('{"a":42,"b":43,"c":44,"d":97}', '{a,d,e}');
Run Code Online (Sandbox Code Playgroud)
会返回这个:
{"a":42,"d":97}
Run Code Online (Sandbox Code Playgroud)
有点像jsonb_path_query_array,但针对的是 kv 对而不是值。
您可以使用运算符删除给定的键-(与您的想法相反)。手册:
\n\n\n
jsonb - text[]\xe2\x86\x92jsonb从左操作数中删除所有匹配的键或数组元素。
\n\n
\'{"a": "b", "c": "d"}\'::jsonb - \'{a,c}\'::text[]\xe2\x86\x92{}
但我不知道内置函数或运算符会执行您所要求的操作(包括当前的 Postgres 15)。
\n值得注意的是,SQL 语句则相反SELECT。在那里你会得到一个带有 的肯定列表SELECT a,d,e FROM tbl,但不能简单地获取“除 [a,d,e] 之外的所有列”,就像你可以获取“除 [a,d,e] 之外的所有键”一样一样。我希望每个功能都有互补的功能。
也想不出使用 SQL/JSON 路径语言(Postgres 12+)的简单方法。
\njsonb您可以创建一个简单的函数,例如:
\nCREATE OR REPLACE FUNCTION f_jsonb_select_keys(_js jsonb, _keys text[])\n RETURNS jsonb\n LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS\n$func$\nSELECT jsonb_object_agg(t.key, t.value)\nFROM jsonb_each(_js) t\nWHERE t.key = ANY (_keys);\n$func$;\nRun Code Online (Sandbox Code Playgroud)\ndb<>在这里摆弄
\n称呼:
\nSELECT f_jsonb_select_keys(\'{"a":42,"b":43,"c":44,"d":97}\', \'{a,d,e}\');\nRun Code Online (Sandbox Code Playgroud)\n返回:
\n{"a":42,"d":97}\nRun Code Online (Sandbox Code Playgroud)\n对于 NULL 或任一参数的空输入,您会得到 NULL(如小提琴所示)。所以我声明了该函数STRICT(又名RETURNS NULL ON NULL INPUT),即使嵌套函数jsonb_object_agg()不是STRICT。可能扰乱函数内联,但由于无论如何都不能内联这个函数(包含聚合函数),所以我们也可以。看:
IMMUTABLE只是有点真实。继续阅读。
jsonb不保留键的顺序(键在内部以确定性方式排序),因此我们无需担心聚合中输入行的顺序。除非存在重复项,否则以输入的最新副本为准。手册:
\n\n由于该
\njson类型存储输入文本的精确副本,\n它将保留标记之间语义上无关紧要的空白,\以及 JSON 对象中键的顺序。此外,如果值中的 JSON 对象多次包含相同的键,则所有键/值对都会保留。(处理函数将最后一个值视为操作值。)相比之下,jsonb不保留空白、不保留对象键的顺序,并且不保留重复的对象键。如果在输入中指定了重复的键,\n则仅保留最后一个值。
这意味着,如果输入中可以有重复的键,则行的顺序很重要。我的函数没有显式对行进行排序,因此结果不会严格为IMMUTABLE. 但输入直接来自jsonb_each()并且不能有重复的键jsonb(与 不同json)。输入键数组中可能存在的重复项与= ANY构造无关。所以重复永远不会发生。IMMUTABLE毕竟。
同样,这将禁止函数内联——如果它一开始就可以内联的话。
\njson为了完整起见:与 相同,而不是jsonjsonb:
第一个变体不会尝试保留给定的键顺序,并且它消除了输入键数组中可能的重复项(但不会消除输入中可能的重复项json!):
CREATE OR REPLACE FUNCTION f_json_select_keys(_js json, _keys text[])\n RETURNS json\n LANGUAGE sql STABLE STRICT PARALLEL SAFE AS\n$func$\nSELECT json_object_agg (t.key, t.value)\nFROM json_each(_js) t\nWHERE key = ANY (_keys);\n$func$;\nRun Code Online (Sandbox Code Playgroud)\n第二种变体保留给定的键顺序并保留所有可能的重复项。(如果相同的键在json输入中为 2x,在输入键数组中为 3x,则在结果中得到 6x。):
CREATE OR REPLACE FUNCTION f_json_select_keys(_js json, _keys text[])\n RETURNS json\n LANGUAGE sql STABLE STRICT PARALLEL SAFE AS\n$func$\nSELECT json_object_agg (t.key, t.value ORDER BY ord)\nFROM unnest(_keys) WITH ORDINALITY k(key, ord)\nJOIN json_each(_js) t USING (key);\n$func$;\nRun Code Online (Sandbox Code Playgroud)\n关于WITH ORDINALITY:
我创建这些json函数是STABLE因为json_object_agg()is 只是STABLE与 相对jsonb_object_agg(),即IMMUTABLE相对。
你可以使用json_build_object (\'a\', js->\'a\', \'d\', js->\'d\', \'e\', js->\'e\'),但这将包括所有键,如果未找到则为 NULL 值。不完全是你的要求。而且您无法区分丢失的键和具有实际 NULL 值的相同键之间的区别。
| 归档时间: |
|
| 查看次数: |
4867 次 |
| 最近记录: |