# 9.16.JSON函数和运算符
本节介绍:
用于处理和创建JSON数据的函数和运算符
SQL/JSON路径语言
要了解有关SQL/JSON标准的更多信息,请参阅[sqltr-19075-6]。有关PostgreSQL支持的JSON类型的详细信息,请参阅第8.14节.
# 9.16.1.处理和创建JSON数据
表9.44显示可用于JSON数据类型的运算符(请参阅第8.14节)。此外,中所示的常用比较运算符表9.1可供jsonb
,但不是为了json
.比较运算符遵循中概述的B树操作的排序规则第8.14.4节.
表9.44.json
和jsonb
操作员
操作人员 描述 例子 |
---|
杰森 -> 整数 → 杰森 jsonb -> 整数 → jsonb 摘录* n *JSON数组的第个元素(数组元素从零开始索引,但负整数从末尾开始计数)。“[{a:“foo”},{b:“bar”},{c:“baz”}]::json → {“c”:“baz”} “[{a:“foo”},{b:“bar”},{c:“baz”}]::json->-3 → {“a”:“foo”} |
杰森 -> 文本 → 杰森 jsonb -> 文本 → jsonb 使用给定的键提取JSON对象字段。 “{a:{b:“foo”}}”::json->“a” → {“b”:“foo”} |
json ->> 整数 → 文本 jsonb ->> 整数 → 文本 摘录* n *'JSON数组的第个元素,如文本 .[1,2,3]::json->2 → 3. |
json ->> 文本 → 文本 jsonb ->> 文本 → 文本 使用给定的键提取JSON对象字段,如下所示: 文本 .“{”a:1,“b:2}”::json->“b” → 2. |
json #> 文本[] → json jsonb #> 文本[] → jsonb 在指定路径提取JSON子对象,其中路径元素可以是字段键或数组索引。 “{a:{b:[“foo”,“bar”]}}”: → “酒吧” |
json #>> 文本[] → 文本 jsonb #>> 文本[] → 文本 在指定路径提取JSON子对象,如下所示: 文本 .“{a:{b:[“foo”,“bar”]}}”::json#>>“{a,b,1}” → 酒吧 |
# 笔记
如果JSON输入没有与请求匹配的正确结构,字段/元素/路径提取运算符将返回NULL,而不是失败;例如,如果不存在这样的键或数组元素。
还有一些运营商只是为了jsonb
,如中所示表9.45. 第8.14.4节描述如何使用这些运算符有效搜索索引jsonb
数据
表9.45.额外的jsonb
操作员
操作人员 描述 例子 |
---|
jsonb @> jsonb → 布尔值 第一个JSON值是否包含第二个JSON值?(见第8.14.3节有关遏制的详细信息。) “{”a:1,“b:2}”::jsonb@>“{”b:2}”::jsonb → t |
jsonb <@ jsonb → 布尔值 第一个JSON值是否包含在第二个JSON值中? “{b:2}”:jsonb<@{a:1,“b:2}”:jsonb → t |
jsonb ? 文本 → 布尔值 文本字符串在JSON值中是否作为顶级键或数组元素存在? “{a:1,“b:2}”::jsonb?”b' → t “[“a”、“b”、“c”]::jsonb?”b' → t |
jsonb ?| 文本[] → 布尔值 文本数组中是否有任何字符串作为顶级键或数组元素存在? “{a:1,b:2,c:3}”:数组['b','d'] → t |
jsonb ?& 文本[] → 布尔值 文本数组中的所有字符串都作为顶级键或数组元素存在吗? “[“a”、“b”、“c”]::jsonb?&数组['a','b'] → t |
jsonb || jsonb → jsonb 连接两个 jsonb 价值观连接两个数组会生成一个包含每个输入的所有元素的数组。连接两个对象将生成一个包含其关键帧并集的对象,当存在重复关键帧时,将获取第二个对象的值。所有其他情况都是通过将非数组输入转换为单个元素数组来处理的,然后继续处理两个数组。不递归操作:只合并顶级数组或对象结构。“[“a”,“b”]::jsonb | |”[“a”,“d”]::jsonb → [“a”、“b”、“a”、“d”] “{a:“b”}::jsonb | |”{c:“d”}::jsonb → {a:“b”,“c:“d”} [1,2]::jsonb |'3'::jsonb → [1, 2, 3] {a:“b”}::jsonb |'42'::jsonb → [{“a”:“b”},42] 要将一个数组作为单个条目附加到另一个数组中,请将其包装到另一个数组层中,例如: [1,2]::jsonb | | jsonb_build_array(“[3,4]”::jsonb) → [1, 2, [3, 4]] |
jsonb -对。 文本 → jsonb 从JSON对象中删除键(及其值),或从JSON数组中删除匹配的字符串值。 {“a”:“b”,“c”:“d”}'::jsonb → {“c”:“d”} “[“a”、“b”、“c”、“b”]::jsonb → [“a”,“c”] |
jsonb -对。 文本[] → jsonb 从左操作数中删除所有匹配的键或数组元素。 “{a:“b”,“c:“d”}”::jsonb j'{a,c}'::text[] → {} |
jsonb - 整数 → jsonb 删除具有指定索引的数组元素(负整数从末尾开始计数)。如果JSON值不是数组,则引发错误。 “[“a”,“b”]::jsonb-1 → [“a”] |
jsonb #- 文本[] → jsonb 删除指定路径上的字段或数组元素,其中路径元素可以是字段键或数组索引。 “[“a”,“b”:1}]::jsonb#-“{1,b}” → [“a”,{}] |
jsonb @? jsonpath → 布尔值 JSON路径是否为指定的JSON值返回任何项? “{a:[1,2,3,4,5]}::jsonb@?”$。a[*]?(@ > 2)' → t |
jsonb @@ jsonpath → 布尔值 返回指定JSON值的JSON路径谓词检查结果。只考虑结果的第一项。如果结果不是布尔值,则 无效的 被退回。“{a:[1,2,3,4,5]}”::jsonb@@@。a[*]>2' → t |
# 笔记
这个jsonpath
操作员@?
和@@
抑制以下错误:缺少对象字段或数组元素、意外的JSON项类型、日期时间和数字错误。这个jsonpath
-下面描述的相关功能也可以用来抑制这些类型的错误。在搜索不同结构的JSON文档集合时,此行为可能会有所帮助。
表9.46显示可用于构造的函数json
和jsonb
价值观
表9.46.JSON创建函数
作用 描述 例子 |
---|
给_json (咯咯笑)任何元素 →杰森 给_jsonb (咯咯笑)任何元素 →jsonb 将任何SQL值转换为 杰森 或jsonb 数组和组合被递归地转换为数组和对象(多维数组在JSON中成为数组的数组)。否则,如果SQL数据类型转换为杰森 cast函数将用于执行转换;[a]否则,将生成标量JSON值。对于除数字、布尔值或空值以外的任何标量,将使用文本表示,并根据需要进行转义,使其成为有效的JSON字符串值。致_json('弗雷德说了声“嗨”。'::(文本) → 弗雷德打招呼。"" 致_jsonb(第42排,弗雷德说“嗨”。::(文本) → {“f1”:42,“f2”:“弗雷德说了一声你好。” |
数组到json (咯咯笑)任意数组 [(笑声),布尔值 ]→json 将SQL数组转换为JSON数组。行为与 给_json 但是,如果可选的布尔参数为true,则会在顶级数组元素之间添加换行符。数组到json ( {1,5},{99100}::int[] ) → [[1,5],[99,100]] |
第_行至第_行 ( 记录 [, 布尔值 ] ) → json 将SQL复合值转换为JSON对象。行为与 给_json 但是,如果可选布尔参数为true,则将在顶级元素之间添加换行符。第_行到第json行(第(1行,'foo')) → {“f1”:1,“f2”:“foo”} |
json_构建_数组 ( 可变的 “任何” ) → json jsonb_构建_阵列 ( 可变的 “任何” ) → jsonb 从可变参数列表中构建一个可能是异构类型的JSON数组。每个参数都按照 给_json 或给_jsonb .json_构建_数组(1,2,'foo',4,5) → [1,2,“foo”,4,5] |
json_build_对象 ( 可变的 “任何” ) → json jsonb_构建_对象 ( 可变的 “任何” ) → jsonb 从可变参数列表中构建JSON对象。按照惯例,参数列表由交替的键和值组成。关键论点被强制转换成文本;值参数按照 给_json 或给_jsonb .json_build_对象('foo',1,2,row(3,'bar')) → {“foo”:1,2:{“f1”:3,f2:“bar”} |
json_对象 ( 文本[] ) → json jsonb_对象 ( 文本[] ) → jsonb 从文本数组中构建JSON对象。数组必须只有一个维度的成员数为偶数,在这种情况下,它们被视为交替的键/值对,或者只有两个维度的成员数为偶数,这样每个内部数组就只有两个元素,它们被视为键/值对。所有值都转换为JSON字符串。 json_对象(“{a,1,b,“def”,c,3.5}”) → {“a”:“1”,“b”:“def”,“c”:“3.5”} json_对象(“{a,1},{b,def},{c,3.5}”) → {“a”:“1”,“b”:“def”,“c”:“3.5”} |
json_对象 ( 钥匙 文本[] , 价值观 文本[] ) → json jsonb_对象 ( 钥匙 文本[] , 价值观 文本[] ) → jsonb 这种形式的 json_对象 从单独的文本数组中成对获取键和值。否则,它与单参数形式相同。json_对象({a,b},{1,2}) → {“a”:“1”,“b”:“2”} |
[a] 例如商店extension的演员阵容来自商店 到json 因此商店 通过JSON创建函数转换的值将表示为JSON对象,而不是原始字符串值。 |
表9.47显示可用于处理的函数json
和jsonb
价值观
表9.47.JSON处理函数
作用 描述 例子 | ||||||||
---|---|---|---|---|---|---|---|---|
json_数组_元素 ( json ) → json集合 jsonb_数组_元素 ( jsonb ) → jsonb集合 将顶级JSON数组扩展为一组JSON值。 从json_数组_元素中选择* → ``<br/>值<br/>------------<br/>1<br/>真<br/>[2,假]<br/><br/> | ||||||||
json_数组_元素_文本 ( json ) → 文本集 jsonb_数组_元素_文本 ( jsonb ) → 文本集 将顶级JSON数组扩展为一组 文本 价值观从json_数组_元素_文本(“[“foo”,“bar”]”)中选择* → ``<br/>value<br/>------------<br/>foo<br/>bar<br/><br/> | ||||||||
json_数组_长度 ( json ) → 整数 jsonb_数组_长度 ( jsonb ) → 整数 返回顶级JSON数组中的元素数。 json_数组_长度('[1,2,3,{f1:1,f2:[5,6]},4]')) → 5. | ||||||||
每个人 ( json ) → 一套记录 ( 钥匙 文本 , 价值 json )各就各位 ( jsonb ) → 一套记录 ( 钥匙 文本 , 价值 jsonb )将顶级JSON对象扩展为一组键/值对。 分别从json_中选择*(“{”a:“foo”,“b:“bar”}”) → ````` 钥匙 | 价值 -----+------- A. | “福” b | “酒吧” ``` | |||||
json_每个_文本 ( json ) → 一套记录 ( 钥匙 文本 (笑声)价值 文本 )jsonb_每个_文本 (咯咯笑)jsonb →一套记录 (咯咯笑)钥匙 文本 (笑声)价值 文本 )将顶级JSON对象扩展为一组键/值对。孩子们回来了* 价值 *这将是一种文本 .(从json_中)选择每个_文本(“{”a:“foo”,“b:“bar”}”) → <br/><br/>" 钥匙 | 价值 ---+----- 和 | 福 b | 酒吧 "`` | |||||
json_提取_路径 (咯咯笑)来自_json 杰森 (笑声)可变的 路径元素 文本[] →杰森 jsonb_提取_路径 (咯咯笑)来自_json jsonb (笑声)可变的 路径元素 文本[] →jsonb 在指定路径提取JSON子对象。(这在功能上等同于 #> 运算符,但在某些情况下,将路径输出写入变量列表可能更方便。)json_extract_path(“{”f2“:{”f3“:1}”,f4“:{”f5“:99,“f6“:“foo”},“,”f4“,”f6“) → “福” | ||||||||
json_提取_路径_文本 (咯咯笑)来自_json 杰森 (笑声)可变的 路径元素 文本[] →文本 jsonb_提取路径_文本 (咯咯笑)来自_json jsonb (笑声)可变的 路径元素 文本[] →文本 在指定路径提取JSON子对象,如下所示: 文本 (这在功能上等同于#>> 接线员。)json_extract_path_text(“{”f2“:{”f3:1},“f4“:{”f5:99,“f6“:“foo”},“,”f4“,”f6“) → 福 | ||||||||
json_对象_键 (咯咯笑)杰森 →文本集 jsonb_对象_键 (咯咯笑)jsonb →文本集 返回顶级JSON对象中的键集。 从json_对象_键(“{”f1:“abc”,“f2:{”f3:“a”,“f4:“b”}”)中选择 → ``<br/>json_object_keys<br/>---------------------------f1<br/>f2<br/><br/> | ||||||||
人口记录 (咯咯笑)基础 任何元素 (笑声)来自_json 杰森 →任何元素 jsonb_人口记录 (咯咯笑)基础 任何元素 (笑声)来自_json jsonb →任何元素 将顶级JSON对象扩展为具有* 基础 论点JSON对象将被扫描,以查找名称与输出行类型的列名匹配的字段,并将其值插入到输出的这些列中。(与任何输出列名不对应的字段将被忽略。)在典型的使用中基础 只是无效的 ,这意味着任何与任何对象字段不匹配的输出列都将被空值填充。然而,如果基础 *不是吗无效的 然后,它包含的值将用于不匹配的列。要将JSON值转换为输出列的SQL类型,请按顺序应用以下规则: *JSON空值在所有情况下都会转换为SQL空值。 *如果输出列的类型为 json 或jsonb ,JSON值正好被复制。*如果输出列是复合(行)类型,而JSON值是JSON对象,则通过递归应用这些规则,将对象的字段转换为输出行类型的列。 *同样,如果输出列是数组类型,JSON值是JSON数组,则通过递归应用这些规则,将JSON数组的元素转换为输出数组的元素。 *否则,如果JSON值是一个字符串,则该字符串的内容将提供给列数据类型的输入转换函数。 *否则,JSON值的普通文本表示形式将提供给列数据类型的输入转换函数。 虽然下面的示例使用一个常量JSON值,但典型的用法是引用 json 或jsonb 从查询的从…起 条款写json_填充_记录 在从…起 子句是一种很好的做法,因为所有提取的列都可以使用,而无需重复的函数调用。创建类型子类型为(d int,e text); 创建类型myrowtype为(a int,b text[],c subrowtype); 从json填充记录中选择* → ````` A. | b | c ---+-----------+------------- 1. | {2,“a b”} | (4,“a b c”) ``` | ||||
json_填充_记录集 ( 基础 任何元素 , 来自_json json ) → 任意元素集 jsonb_填充_记录集 ( 基础 任何元素 , 来自_json jsonb ) → 任意元素集 将对象的顶级JSON数组扩展为一组具有* 基础 *论点JSON数组中的每个元素都按照上述步骤进行处理json[b]_填充_记录 .将类型twoint创建为(a int,b int); 从json_populate_记录集(null::twoints,[{a:1,b:2},{a:3,b:4}])中选择* → ````` A. | b ---+--- 1. | 2. 3. | 4. ``` | |||||
json_to_记录 ( json ) → 记录 jsonb_to_记录 ( jsonb ) → 记录 将顶级JSON对象扩展到具有由 像 条款(与所有函数一样记录 ,调用查询必须使用像 条款。)输出记录是从JSON对象的字段中填充的,其填充方式与前面为json[b]_填充_记录 。由于没有输入记录值,因此不匹配的列总是用空值填充。创建类型myrowtype为(a int,b text); 选择*从json_到_记录('{a:1,b:[1,2,3],“c:[1,2,3],“e:[1,2,3],“e:[1,2,3],“bar”,“r:{a:123,b:[ABC”}}])作为x(a int,b text,c int[],d text,r myrowtype) → ````` A. | b | c | d | r ---+---------+---------+---+--------------- 1. | [1,2,3] | {1,2,3} | (123,“a b c”) ``` | |
json_到_记录集 ( json ) → 一套记录 jsonb_to_记录集 (jsonb ) →setof record Expands the top-level JSON array of objects to a set of rows having the composite type defined by an AS clause. (As with all functions returningrecord , the calling query must explicitly define the structure of the record with anAS clause.) Each element of the JSON array is processed as described above forjson[b]_populate_record .select * from json_to_recordset('[{"a":1,"b":"foo"}, {"a":"2","c":"bar"}]') as x(a int, b text) →````` a | b ---+----- 1 | foo 2 | ``` | |||||
jsonb_set (target jsonb ,path text[] , 新价值 jsonb [, 如果缺少,请创建_ _布尔值 ] ) → jsonb<br/><br/>退换商品* 目标*与指定的项目* 路径*取而代之的* 新价值*,或与* 新价值*添加如果* 如果缺少,请创建*为true(这是默认值),并且由* 路径*不存在。路径中的所有早期步骤都必须存在,或者* 目标*返回时保持不变。与面向路径的运算符一样,出现在* 路径*从JSON数组的末尾开始计数。如果最后一个路径步骤是超出范围的数组索引,并且* 如果缺少,请创建*如果为true,则如果索引为负,则在数组开头添加新值,如果索引为正,则在数组末尾添加新值。<br/><br/> jsonb_集(“[{f1:1,f2:null},2,null,3]”,“{0,f1},“[2,3,4]”,false)→ [{“f1”:[2,3,4],“f2”:null},2,null,3]<br/><br/> jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]')→ [{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]` | ||||||||
jsonb_set_lax (目标 jsonb ,小路 文本[] ,新值 jsonb [,create_if_missing 布尔值 [,null*value_treatment_ 文本 ]] ) →jsonb 如果 新值 不是空值 , 行为与jsonb_set .否则按照null_value_treatment *必须是其中之一'raise_exception' ,'use_json_null' ,'删除键' , 要么'return_target' .默认是'use_json_null' .jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null) →[{"f1":null,"f2":null},2,null,3] jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target') →[{“f1”:99,“f2”:空},2] | ||||||||
jsonb_insert (目标 jsonb ,小路 文本[] ,新值 jsonb [,插入后*_布尔值 * ]) → jsonb<br/><br/>退货* 目标*和* 新值*插入。如果指定的项目* 小路*是一个数组元素,* 新值*将插入该项目之前,如果* 插入后*为假(这是默认值),或者在它之后如果* 插入后*是真的。如果指定的项目* 小路*是一个对象场,* 新值*仅当对象尚未包含该键时才会插入。路径中的所有早期步骤都必须存在,否则* 目标*原样返回。与面向路径的运算符一样,出现在* 小路*从 JSON 数组的末尾开始计数。如果最后一个路径步骤是超出范围的数组索引,则如果索引为负,则将新值添加到数组的开头,如果索引为正,则将新值添加到数组的末尾。<br/><br/> jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"')→ {"a": [0, "new_value", 1, 2]}<br/><br/> jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true)→ {"a": [0, 1, "new_value", 2]}` | ||||||||
json_strip_nulls (json ) →json jsonb_strip_nulls (jsonb ) →jsonb 从给定的 JSON 值中递归删除所有具有空值的对象字段。不是对象字段的空值保持不变。 json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]') →[{"f1":1},2,null,3] | ||||||||
jsonb_path_exists (目标 jsonb ,小路 json路径 [,变量 jsonb [,沉默的* 布尔值 ]] ) →布尔值 检查 JSON 路径是否返回指定 JSON 值的任何项目。如果 变量 参数被指定,它必须是一个 JSON 对象,并且它的字段提供命名值以替换到json路径 表达。如果无声 *参数被指定并且是真的 ,该函数抑制与@? 和@@ 运营商做。jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,“最大”:4}') →吨 | ||||||||
jsonb_path_match (目标 jsonb ,小路 json路径 [,变量 jsonb [,无声* 布尔值 ]] ) →布尔值 返回指定 JSON 值的 JSON 路径谓词检查的结果。只考虑结果的第一项。如果结果不是布尔值,则 空值 被退回。可选的变量 和无声 *参数的作用与 for 相同jsonb_path_exists .jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{“最小”:2,“最大”:4}') →吨 | ||||||||
jsonb_path_query (目标 jsonb ,小路 json路径 [,变量 jsonb [,无声* 布尔值 ]] ) →jsonb 集合 返回指定 JSON 值的 JSON 路径返回的所有 JSON 项。可选的 变量 和无声 *参数的作用与 for 相同jsonb_path_exists .select * from jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{“最小”:2,“最大”:4}') →``<br/> jsonb_path_query<br/>------------------<br/> 2<br/> 3<br/> 4<br/><br/> | ||||||||
jsonb_path_query_array (目标 jsonb ,小路 json路径 [,变量 jsonb [,沉默的* 布尔值 ]] ) →jsonb 以 JSON 数组的形式返回指定 JSON 值的 JSON 路径返回的所有 JSON 项。可选的 变量 和沉默的 *参数的作用与 for 相同jsonb_path_exists .jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,“最大”:4}') →[2, 3, 4] | ||||||||
jsonb_path_query_first (目标 jsonb ,小路 json路径 [,变量 jsonb [,无声* 布尔值 ]] ) →jsonb 返回指定 JSON 值的 JSON 路径返回的第一个 JSON 项。退货 空值 如果没有结果。可选的变量 和无声 *参数的作用与 for 相同jsonb_path_exists .jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,“最大”:4}') →2 | ||||||||
jsonb_path_exists_tz (目标 jsonb , 小路 json路径 [,变量 jsonb [, 无声 布尔值 ]] ) → 布尔值 jsonb_path_match_tz ( 目标 jsonb , 小路 json路径 [,变量 jsonb [, 无声 布尔值 ]] ) → 布尔值 jsonb_path_query_tz ( 目标 jsonb , 小路 json路径 [,变量 jsonb [, 无声 布尔值 ]] ) → jsonb 集合 jsonb_path_query_array_tz ( 目标 jsonb , 小路 json路径 [,变量 jsonb [, 无声 布尔值 ]] ) → jsonb jsonb_path_query_first_tz ( 目标 jsonb (笑声)路径 jsonpath [,瓦尔斯 jsonb [(笑声),沉默的* *布尔值 ]→jsonb 这些函数与上面描述的对应函数一样,没有 _tz 后缀,但这些函数支持需要时区识别转换的日期/时间值的比较。下面的示例需要解释仅日期值2015-08-02 作为带有时区的时间戳,因此结果取决于当前时区背景。由于这种依赖关系,这些函数被标记为稳定的,这意味着这些函数不能在索引中使用。它们的对应项是不可变的,因此可以在索引中使用;但如果被要求进行这样的比较,他们会出错。jsonb_路径_存在(“[”2015-08-01 12:00:00-05“]),“$[*]?(@.datetime()<”2015-08-02)。datetime()) →t | ||||||||
杰森布 (咯咯笑)jsonb →文本 将给定的JSON值转换为打印精美的缩进文本。 jsonb_pretty(“[{”f1:1,“f2:null},2]”) →``<br/>[<br/> {<br/> "f1": 1,<br/> "f2": null<br/> },<br/> 2<br/>]<br/><br/> | ||||||||
json_typeof (json ) →text jsonb_typeof (jsonb ) →text Returns the type of the top-level JSON value as a text string. Possible types are object ,array ,string ,number ,boolean , andnull . (Thenull result should not be confused with an SQL NULL; see the examples.)json_typeof('-123.4') →number json_typeof('null'::json) → 无效的 json_typeof(NULL::json)为NULL → t |
另见第9.21节对于聚合函数json_agg
它将记录值聚合为JSON,即聚合函数json_object_agg
它将成对的值聚合到一个JSON对象中马
等价物,jsonb_agg
和jsonb_object_agg
.
# 9.16.2.SQL/JSON路径语言
SQL/JSON路径表达式指定要从JSON数据中检索的项,类似于用于SQL访问XML的XPath表达式。在PostgreSQL中,路径表达式实现为jsonpath
数据类型,可以使用中描述的任何元素第8.14.7节.
JSON查询函数和运算符将提供的路径表达式传递给路径引擎用于评估。如果表达式与查询的JSON数据匹配,则返回相应的JSON项或项集。路径表达式是用SQL/JSON路径语言编写的,可以包括算术表达式和函数。
路径表达式由jsonpath
数据类型。路径表达式通常从左向右求值,但可以使用括号更改操作顺序。如果计算成功,将生成一系列JSON项,并将计算结果返回给完成指定计算的JSON查询函数。
要引用被查询的JSON值上下文项),使用$
路径表达式中的变量。它后面可以跟一个或多个存取运算符,它逐级向下遍历JSON结构,以检索上下文项的子项。接下来的每个操作符都处理上一个评估步骤的结果。
例如,假设您想解析来自GPS跟踪器的一些JSON数据,例如:
{
"track": {
"segments": [
{
"location": [ 47.763, 13.4034 ],
"start time": "2018-10-14 10:05:14",
"HR": 73
},
{
"location": [ 47.706, 13.2635 ],
"start time": "2018-10-14 10:39:21",
"HR": 135
}
]
}
}
要检索可用的轨迹段,需要使用.*
钥匙*
访问器操作符向下遍历周围的JSON对象:
$.track.segments
要检索数组的内容,通常使用[*]
操作人员例如,以下路径将返回所有可用轨迹段的位置坐标:
$.track.segments[*].location
要仅返回第一段的坐标,可以在[]
接线员。回想一下,JSON数组索引是0相对的:
$.track.segments[0].location
每个路径评估步骤的结果可以由一个或多个jsonpath
中列出的运算符和方法第9.16.2.2节.每个方法名称前面必须有一个点。例如,可以获得数组的大小:
$.track.segments.size()
更多使用jsonpath
路径表达式中的运算符和方法如下所示第9.16.2.2节.
定义路径时,还可以使用一个或多个路径过滤表达式这项工作类似于哪里
SQL中的子句。筛选器表达式以问号开头,并在括号中提供条件:
? (condition)
过滤器表达式必须在应用它们的路径求值步骤之后写入。该步骤的结果将被过滤,以仅包括满足所提供条件的项目。SQL/JSON定义了三值逻辑,因此条件可以是符合事实的
, 错误的
或未知的
这个未知的
值的作用与SQL相同无效的
并且可以用未知
谓语进一步的路径计算步骤只使用筛选器表达式返回的那些项符合事实的
.
中列出了可在筛选表达式中使用的函数和运算符表9.49.在筛选器表达式中@
变量表示被过滤的值(即,前面路径步骤的一个结果)。之后可以编写访问器运算符@
检索组件项。
例如,假设要检索所有高于130的心率值。可以使用以下表达式实现这一点:
$.track.segments[*].HR ? (@ > 130)
要获取具有此类值的段的开始时间,必须在返回开始时间之前过滤掉不相关的段,因此过滤器表达式应用于上一步,条件中使用的路径不同:
$.track.segments[*] ? (@.HR > 130)."start time"
如果需要,可以按顺序使用多个过滤器表达式。例如,以下表达式选择包含具有相关坐标和高心率值的位置的所有分段的开始时间:
$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"
还允许在不同嵌套级别使用过滤器表达式。以下示例首先按位置过滤所有分段,然后返回这些分段的高心率值(如果可用):
$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)
也可以将过滤器表达式嵌套在彼此之间:
$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()
如果该表达式包含任何具有高心率值的片段,或包含空序列,则该表达式返回轨迹的大小。
PostgreSQL对SQL/JSON路径语言的实现与SQL/JSON标准存在以下偏差:
路径表达式可以是布尔谓词,尽管SQL/JSON标准只允许在过滤器中使用谓词。这对于执行《公约》是必要的
@@
操作人员例如,以下jsonpath
表达式在PostgreSQL中有效:$.track.segments[*].HR < 70
在对应用程序中使用的正则表达式模式的解释上存在细微差异
比如_regex
过滤器,如中所述第9.16.2.3节.
# 9.16.2.1.严与松
查询JSON数据时,路径表达式可能与实际的JSON数据结构不匹配。试图访问对象或数组元素中不存在的成员会导致结构错误。SQL/JSON路径表达式有两种处理结构错误的模式:
lax(默认)-路径引擎隐式地将查询的数据调整到指定的路径。任何剩余的结构错误都将被抑制并转换为空的SQL/JSON序列。
严格-如果发生结构错误,则会引发错误。
如果JSON数据不符合预期的模式,lax模式有助于JSON文档结构和路径表达式的匹配。如果操作数与特定操作的要求不匹配,则可以在执行此操作之前将其自动包装为SQL/JSON数组,或通过将其元素转换为SQL/JSON序列将其展开。此外,比较运算符会在lax模式下自动展开其操作数,因此您可以直接比较SQL/JSON数组。大小为1的数组被视为等于其唯一元素。只有在以下情况下,才会执行自动展开:
路径表达式包含
类型()
或大小()
方法,分别返回数组中元素的类型和数量。查询的JSON数据包含嵌套数组。在这种情况下,只有最外层的数组被展开,而所有内部数组保持不变。因此,隐式展开在每个路径计算步骤中只能向下一级。
例如,当查询上面列出的GPS数据时,您可以从使用lax模式时它存储了一组段的事实中提取:
lax $.track.segments.location
在严格模式下,指定的路径必须与查询的JSON文档的结构完全匹配,才能返回SQL/JSON项,因此使用此路径表达式将导致错误。要获得与lax模式相同的结果,必须显式打开部分
数组:
strict $.track.segments[*].location
这个.**
当使用lax模式时,访问器可能会导致令人惊讶的结果。例如,下面的查询选择每个人力资源
价值两倍:
lax $.**.HR
这是因为.**
访问器选择两个部分
数组及其每个元素,而.人力资源
当使用lax模式时,accessor会自动打开阵列。为了避免意外的结果,我们建议使用.**
仅在严格模式下访问器。下面的查询将选择每个人力资源
价值只有一次:
strict $.**.HR
# 9.16.2.2.SQL/JSON路径运算符和方法
表9.48显示中可用的运算符和方法jsonpath
。请注意,虽然一元运算符和方法可以应用于前面路径步骤产生的多个值,但二元运算符(加法等)只能应用于单个值。
表9.48. jsonpath
算子和方法
操作员/方法 描述 例子 |
---|
数字 + 数字 → * 数字* 附加 jsonb_路径_查询(“[2]”,“$[0]+3”) → 5. |
+ 数字 → * 数字* 一元加号(无操作);与加法不同,它可以迭代多个值 jsonb_路径_查询_数组('{“x”:[2,3,4]}','+$.x') → [2, 3, 4] |
数字 - 数字 → * 数字* 扣除 jsonb_路径_查询(“[2]”,“[7-$[0]”) → 5. |
- 数字 → * 数字* 反面与减法不同,它可以迭代多个值 jsonb_路径_查询_数组('{“x”:[2,3,4]}','-$.x') → [-2, -3, -4] |
数字 * 数字 → * 数字* 乘法 jsonb_路径_查询(“[4]”,“[2*$[0]”) → 8. |
数字 / 数字 → * 数字* 分开 jsonb_路径_查询(“[8.5]”,“$[0]/2”) → 4.2500000000000000 |
数字 % 数字 → * 数字* 模(余数) jsonb_路径_查询(“[32]”,“$[0]%10”) → 2. |
价值 . 类型() → * 一串* JSON项的类型(请参阅 json_类型 )jsonb_路径_查询_数组('[1,2',{}]','$[*].type()') → [“数字”、“字符串”、“对象”] |
价值 . 大小() → * 数字* JSON项的大小(数组元素数,如果不是数组,则为1) jsonb_路径_查询(“{”m:[11,15]},“$.m.size()”) → 2. |
价值 . 双() → * 数字* 从JSON数字或字符串转换而来的近似浮点数 jsonb_路径_查询('{“len”:“1.9”}','$.len.double()*2') → 3.8 |
数字 . 天花板() → * 数字* 大于或等于给定数字的最近整数 jsonb_路径_查询(“{”h“:1.3},“$.h.天花板()”) → 2. |
数字 . 楼层() → * 数字* 小于或等于给定数字的最近整数 jsonb_路径_查询(“{”h“:1.7},“$.h.floor()”) → 1. |
数字 . abs() → * 数字* 给定数字的绝对值 jsonb_路径_查询('{“z”:-0.3}','$.z.abs()') → 0.3 |
一串 . 日期时间() → * datetime_类型* (见注)从字符串转换的日期/时间值 jsonb_路径_查询('[“2015-8-1”,“2015-08-12”],'$[*]?(@.datetime()<“2015-08-2”)。datetime())') → "2015-8-1" |
一串 . 约会时间(* 样板*) → * datetime_类型* (见注)使用指定的 到时间戳 样板jsonb_路径_查询_数组('[“12:30”,“18:40”],'$[*].datetime(“HH24:MI”)) → ["12:30:00", "18:40:00"] |
对象 . keyvalue() → * 大堆* 对象的键值对,表示为包含三个字段的对象数组: “钥匙” , “价值” 和“身份证” ; “身份证” 是键值对所属对象的唯一标识符jsonb_路径_查询_数组('{“x”:“20”,“y”:32}','$.keyvalue()')) → [{id:0,key:x,value:20},{id:0,key:y,value:32}] |
# 笔记
的结果类型日期时间()
和约会时间(*
样板*)
方法可以是日期
, 蒂梅茨
, 时间
, 时间戳
或时间戳
.这两种方法都动态确定其结果类型。
这个日期时间()
方法按顺序尝试将其输入字符串与日期
, 蒂梅茨
, 时间
, 时间戳
和时间戳
。它在第一个匹配格式上停止,并发出相应的数据类型。
这个约会时间(*
样板*)
方法根据提供的模板字符串中使用的字段确定结果类型。
这个日期时间()
和约会时间(*
样板*)
方法使用与到时间戳
SQL函数(请参见第9.8节),但有三个例外。首先,这些方法不允许不匹配的模板模式。其次,模板字符串中只允许使用以下分隔符:减号、句号、斜杠、逗号、撇号、分号、冒号和空格。第三,模板字符串中的分隔符必须与输入字符串完全匹配。
如果需要比较不同的日期/时间类型,则应用隐式强制转换。A.日期
价值可以被赋予时间戳
或时间戳
, 时间戳
可以投给时间戳
和时间
到蒂梅茨
.然而,除第一次转换外,所有转换都取决于当前时区设置,因此只能在时区感知范围内执行jsonpath
功能。
表9.49显示可用的筛选器表达式元素。
表9.49. jsonpath
过滤表达式元素
谓词/值 描述 例子 |
---|
价值 == 价值 → 布尔值 相等比较(此运算符和其他比较运算符适用于所有JSON标量值) jsonb_路径_查询_数组(“[1,“a”,1,3]”,“$[*]?(@==1)” → [1, 1] jsonb_路径_查询_数组('[1,“a”,1,3]','$[*]?(@==“a”)) → [“a”] |
价值 != 价值 → 布尔值 价值 <> 价值 → 布尔值 不平等比较 jsonb_路径_查询_数组(“[1,2,1,3]”,“$[*]?(@!=1)” → [2, 3] jsonb_路径_查询_数组('[“a”、“b”、“c”],'$[*]?(@<>“b”)) → [“a”,“c”] |
价值 < 价值 → 布尔值 少于比较 jsonb_路径_查询_数组(“[1,2,3]”,“$[*]?(@<2)” → [1] |
价值 <= 价值 → 布尔值 小于或等于比较 jsonb_路径_查询_数组('[“a”、“b”、“c”]'、'$[*]?(@<=“b”)) → [“a”,“b”] |
价值 > 价值 → 布尔值 大于比较 jsonb_路径_查询_数组(“[1,2,3]”,“$[*]?(@>2)” → [3] |
价值 >= 价值 → 布尔值 大于或等于比较 jsonb_路径_查询_数组(“[1,2,3]”,“$[*]?(@>=2)” → [2, 3] |
符合事实的 → 布尔值 JSON常量 符合事实的 jsonb_路径_查询(“[{”name:“John”,“parent”:false},“{”name:“Chris”,“parent”:true}]”,“$[*]?(@.parent==true)” → {“name”:“Chris”,“parent”:true} |
错误的 → 布尔值 JSON常量 错误的 jsonb_路径_查询(“[{”name:“John”,“parent”:false},“{”name:“Chris”,“parent”:true}]”,“$[*]?(@.parent==false)” → {“name”:“John”,“parent”:false} |
无效的 → * 价值* JSON常量 无效的 (请注意,与SQL不同的是无效的 (正常工作)jsonb_路径_查询('[{“name”:“Mary”,“job”:null},{“name”:“Michael”,“job”:“driver”}],'$[*]?(@.job==null)。名称') → “玛丽” |
布尔值 && 布尔值 → 布尔值 布尔与 jsonb_路径_查询(“[1,3,7]”,“$[*]?(@>1&&@<5)” → 3 |
布尔值 || 布尔值 → 布尔值 布尔或 jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)') → 7 |
! 布尔值 → 布尔值 布尔非 jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))') → 7 |
布尔值 未知 → 布尔值 测试布尔条件是否为 未知 .jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) 未知)') → “富” |
细绳 like_regex 细绳 [ 旗帜 细绳 ] → 布尔值 测试第一个操作数是否与第二个操作数给出的正则表达式匹配,可选地用字符串描述的修改 旗帜 字符(见第 9.16.2.3 节)。jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@like_regex "^ab.*c")') → [“abc”,“abdacb”] jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@like_regex "^ab.*c" flag "i")') → [“abc”,“aBdC”,“abdacb”] |
细绳 以。。开始 细绳 → 布尔值 测试第二个操作数是否是第一个操作数的初始子字符串。 jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@以 "John" 开头)') → “约翰·史密斯” |
存在 ( 路径表达式 ) →布尔值 测试路径表达式是否至少与一个SQL/JSON项匹配。退换商品 未知的 如果路径表达式会导致错误;第二个示例使用此选项来避免在严格模式下出现无此类密钥错误。jsonb_路径_查询(“{”x:[1,2],“y:[2,4]}”,“strict$.*?(存在(@?(@[*]>2))) →[2, 4] jsonb_路径_查询_数组('{“value”:41}',strict$?(exists(@.name))。名称') →[] |
# 9.16.2.3.SQL/JSON正则表达式
SQL/JSON路径表达式允许将文本匹配到具有比如_regex
滤器例如,以下SQL/JSON路径查询将不区分大小写地匹配以英语元音开头的数组中的所有字符串:
$[*] ? (@ like_regex "^[aeiou]" flag "i")
可选的旗帜
字符串可能包含一个或多个字符我
对于不区分大小写的匹配,m
容许^
和$
为了配合新线,s
容许.
匹配一条新线q
引用整个模式(将行为简化为简单的子字符串匹配)。
SQL/JSON标准借用了比如_REGEX
运算符,它反过来使用XQuery标准。PostgreSQL目前不支持比如_REGEX
操作人员因此比如_regex
过滤器使用中描述的POSIX正则表达式引擎实现第9.7.3节。这导致与标准SQL/JSON行为存在各种细微差异,这些差异在第9.7.3.8节但是,请注意,这里描述的标志字母不兼容不适用于SQL/JSON,因为它会将XQuery标志字母转换为与POSIX引擎期望的匹配。
请记住,参数的模式比如_regex
是一个JSON路径字符串文本,根据中给出的规则编写第8.14.7节。这尤其意味着要在正则表达式中使用的任何反斜杠都必须加倍。例如,要匹配只包含数字的根文档的字符串值:
$.* ? (@ like_regex "^\\d+$")