Postgresql 中文操作指南
8.14. JSON Types #
JSON 数据类型用于存储 JSON(JavaScript 对象表示法)数据,如 RFC 7159中所规定。此类数据也可以存储为 text,但 JSON 数据类型的优势在于,它强制要求每个存储的值都根据 JSON 规则有效。还有各种可用于存储在这些数据类型中的数据的 JSON 特定函数和运算符;请参见 Section 9.16。
PostgreSQL 提供了两种用于存储 JSON 数据的类型:json_和 _jsonb。为了实现这些数据类型的查询机制,PostgreSQL 还提供了 _jsonpath_数据类型, Section 8.14.7 中对其进行了说明。
json 和 jsonb 数据类型接受 almost 相同的输入值集。主要的实际区别在于效率。json 数据类型存储输入文本的精确副本,处理函数在每次执行时都必须重新解析;而 jsonb 数据存储在分解的二进制格式中,由于增加了转换开销,其输入速度略慢,但处理速度明显更快,因为无需重新解析。jsonb 还支持索引,这可能是一个显着的优势。
由于 json 类型存储输入文本的精确副本,因此它将保留标记之间的语义无关空格,以及 JSON 对象中键的顺序。此外,如果值中的 JSON 对象包含相同的键不止一次,则保留所有键/值对。(处理函数将最后一个值视为有效值。)相比之下,jsonb 不保留空格,不保留对象键的顺序,也不保留重复的对象键。如果在输入中指定了重复的键,则只保留最后一个值。
一般而言,除非存在非常特殊的需求(例如对象键排序的旧假设),大多数应用程序都应更喜欢将 JSON 数据存储为 jsonb。
RFC 7159 规定 JSON 字符串应编码为 UTF8。因此,如果数据库编码不是 UTF8,则 JSON 类型无法严格符合 JSON 规范。尝试直接包含无法在数据库编码中表示的字符将失败;相反,允许包含可以在数据库编码中表示但不能在 UTF8 中表示的字符。
RFC 7159允许JSON字符串包含由 \u_XXXX_ 表示的Unicode转义序列。在 json 类型的输入函数中,允许Unicode转义,而不管数据库编码如何,而且仅检查其语法正确性(即 \u 后面是否有四个十六进制数字)。但是, jsonb 的输入函数更为严格:它禁止对不能用数据库编码表示的字符进行Unicode转义。 jsonb 类型也拒绝 \u0000 (因为它不能用PostgreSQL的 text 类型表示),并且它坚持正确使用Unicode代理对来指定Unicode基本多语言平面的外部字符。有效的Unicode转义转换为等效的单个字符以进行存储;这包括将代理对折叠成单个字符。
Note
Section 9.16 中描述的许多 JSON 处理函数将把 Unicode 转义转换为常规字符,因此即使它们的输入类型为 json 而不是 jsonb,也仍然会引发刚才描述的同类错误。尽管这允许在不支持已表示字符的数据库编码中简单存储(不做处理)JSON Unicode 转义序列,但 json 输入函数不执行这些检查的事实可被视作一种历史遗留问题。
在将文本 JSON 输入转换为 _jsonb_时,RFC 7159 中描述的基本类型会有效映射到本机 PostgreSQL 类型,如 Table 8.23所示。因此,对于构成有效 _jsonb_数据的额外限制很小,而这些限制不适用于 _json_类型,也不适用于抽象的 JSON,与基础数据类型可以表示的内容限制相对应。值得注意的是,_jsonb_将拒绝超出 PostgreSQL _numeric_数据类型的范围的数字,而 _json_不会。RFC 7159 允许此类实现定义的限制。然而,在实践中,此类问题更有可能发生在其他实现中,因为将 JSON 的 _number_基本类型表示为 IEEE 754 双精度浮点数很常见(RFC 7159 明确预期并允许了这一点)。将 JSON 作为与此类系统互换的格式使用时,应该考虑与 PostgreSQL 最初存储的数据相比丢失数字精度的风险。
相反,如表中所述,对于 JSON 基本类型的输入格式有一些较小的限制,这不适用于相应的 PostgreSQL 类型。
Table 8.23. JSON Primitive Types and Corresponding PostgreSQL Types
JSON primitive type |
PostgreSQL type |
Notes |
string |
text |
\u0000 被禁止,并且表示数据库编码中不可用字符的Unicode转义也被禁止 |
number |
numeric |
禁止 NaN 和 infinity 值 |
boolean |
boolean |
只接受小写的 true 和 false 拼写 |
null |
(none) |
SQL NULL 是一个不同的概念 |
8.14.1. JSON Input and Output Syntax #
JSON 数据类型的输入/输出语法如 RFC 7159 中所指定。
以下是所有有效的 json(或 jsonb)表达式:
-- Simple scalar/primitive value
-- Primitive values can be numbers, quoted strings, true, false, or null
SELECT '5'::json;
-- Array of zero or more elements (elements need not be of same type)
SELECT '[1, 2, "foo", null]'::json;
-- Object containing pairs of keys and values
-- Note that object keys must always be quoted strings
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;
-- Arrays and objects can be nested arbitrarily
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;
如前所述,当输入一个 JSON 值然后在不进行任何其他处理的情况下打印该值时,json 输出与输入相同的文本,而 jsonb 则不会保留空格等语义无关的详细信息。例如,请注意此处差异:
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::json;
json
-------------------------------------------------
{"bar": "baz", "balance": 7.77, "active":false}
(1 row)
SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
jsonb
--------------------------------------------------
{"bar": "baz", "active": false, "balance": 7.77}
(1 row)
一个值得注意的语义无关细节是,在 jsonb 中,数字将根据底层 numeric 类型的行为进行打印。在实践中,这意味着以 E 符号输入的数字将不带符号打印,例如:
SELECT '{"reading": 1.230e-5}'::json, '{"reading": 1.230e-5}'::jsonb;
json | jsonb
-----------------------+-------------------------
{"reading": 1.230e-5} | {"reading": 0.00001230}
(1 row)
但是,jsonb 将保留尾随小数零,如本例所示,即使对于相等性检查之类的目的语义上不重要。
有关用于构造和处理 JSON 值的内置函数和运算符列表,请参见 Section 9.16。
8.14.2. Designing JSON Documents #
将数据表示为 JSON 可以比传统的关联数据模型更灵活,在需求不断变化的环境中非常吸引人。两种方法完全有可能在同一个应用程序中共存并相互补充。但是,即使对于需要最大灵活性的应用程序,仍然建议 JSON 文档具有固定的结构。该结构通常不强制执行(虽然可以声明性地执行某些业务规则),但具有可预测的结构使编写有用的总结表中的一组“文档”(数据)的查询变得更加容易。
存储在表中的 JSON 数据受与任何其他数据类型相同的并发控制考虑。尽管存储大型文档是可行的,但请记住,任何更新都会获取对整行的行级锁。考虑将 JSON 文档限制为可管理的大小,以减少更新事务之间的锁争用。理想情况下,每个 JSON 文档都应该表示一个原子数据,业务规则规定不能合理地进一步细分为可以独立修改的较小数据。
8.14.3. jsonb Containment and Existence #
测试 containment 是 jsonb 的一项重要功能。没有针对 json 类型的一组并行设施。包含测试是否一个 jsonb 文档包含在另一个文档中。除了有注释的,这些示例返回 true:
-- Simple scalar/primitive values contain only the identical value:
SELECT '"foo"'::jsonb @> '"foo"'::jsonb;
-- The array on the right side is contained within the one on the left:
SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;
-- Order of array elements is not significant, so this is also true:
SELECT '[1, 2, 3]'::jsonb @> '[3, 1]'::jsonb;
-- Duplicate array elements don't matter either:
SELECT '[1, 2, 3]'::jsonb @> '[1, 2, 2]'::jsonb;
-- The object with a single pair on the right side is contained
-- within the object on the left side:
SELECT '{"product": "PostgreSQL", "version": 9.4, "jsonb": true}'::jsonb @> '{"version": 9.4}'::jsonb;
-- The array on the right side is not considered contained within the
-- array on the left, even though a similar array is nested within it:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb; -- yields false
-- But with a layer of nesting, it is contained:
SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;
-- Similarly, containment is not reported here:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"bar": "baz"}'::jsonb; -- yields false
-- A top-level key and an empty object is contained:
SELECT '{"foo": {"bar": "baz"}}'::jsonb @> '{"foo": {}}'::jsonb;
一般原则是,包含的对象在结构和数据内容上必须与被包含的对象匹配,在从包含的对象中丢弃一些不匹配的数组元素或对象键/值对后可能匹配。但是请记住,在执行包含匹配时,数组元素的顺序并不重要,并且实际上只考虑一次重复数组元素。
作为对结构必须匹配的一般原则的特殊例外,数组可以包含基本值:
-- This array contains the primitive string value:
SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;
-- This exception is not reciprocal -- non-containment is reported here:
SELECT '"bar"'::jsonb @> '["bar"]'::jsonb; -- yields false
jsonb 也有一个 existence 运算符,它是包含主题的一个变体:它测试字符串(作为一个 text 值给出)是否作为对象键或数组元素出现在 jsonb 值的顶层。这些示例返回 true,除非另有说明:
-- String exists as array element:
SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';
-- String exists as object key:
SELECT '{"foo": "bar"}'::jsonb ? 'foo';
-- Object values are not considered:
SELECT '{"foo": "bar"}'::jsonb ? 'bar'; -- yields false
-- As with containment, existence must match at the top level:
SELECT '{"foo": {"bar": "baz"}}'::jsonb ? 'bar'; -- yields false
-- A string is considered to exist if it matches a primitive JSON string:
SELECT '"foo"'::jsonb ? 'foo';
当涉及许多键或元素时,JSON 对象比数组更适合用于测试包含或是否存在,因为与数组不同,它们在内部针对搜索进行了优化,并且不需要线性搜索。
Tip
因为 JSON 包含是嵌套的,所以适当的查询可以跳过子对象的显式选择。例如,假设我们有一个 doc 列,在该列中包含顶层的对象,其中大多数对象包含 tags 域,该域包含子对象的数组。此查询查找既包含 "term":"paris" 又包含 "term":"food" 的子对象的条目,同时忽略 tags 数组外的任何此类键:
SELECT doc->'site_name' FROM websites
WHERE doc @> '{"tags":[{"term":"paris"}, {"term":"food"}]}';
可以使用下面这种方式实现相同的事情:
SELECT doc->'site_name' FROM websites
WHERE doc->'tags' @> '[{"term":"paris"}, {"term":"food"}]';
但这种方法的灵活性较差,并且通常效率也不高。
另一方面,JSON 存在运算符不是嵌套的:它只会查找 JSON 值顶层的指定键或数组元素。
各种包含和存在运算符与所有其他 JSON 运算符和函数都在 Section 9.16中记录。
8.14.4. jsonb Indexing #
GIN 索引可用于有效搜索大量 jsonb 文档(资料)中出现的键或键/值对。提供了两个 GIN “运算符类”,提供不同的性能和灵活性权衡。
jsonb_的默认 GIN 运算符类支持使用键存在运算符 _?、?|_和 _?&、包含运算符 _@>_以及 _jsonpath_匹配运算符 _@?_和 _@@_进行查询。(有关这些运算符实现的语义的详细信息,请参见 Table 9.46。)使用此运算符类创建索引的一个示例是:
CREATE INDEX idxgin ON api USING GIN (jdoc);
非默认 GIN 运算符类 jsonb_path_ops 不支持键存在运算符,但支持 @>、@? 和 @@。使用此运算符类创建索引的示例:
CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);
考虑从第三方网络服务检索的 JSON 文档的表的示例,其中有记录的模式定义。一个典型的文档是:
{
"guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
"name": "Angela Barton",
"is_active": true,
"company": "Magnafone",
"address": "178 Howard Place, Gulf, Washington, 702",
"registered": "2009-11-07T08:53:22 +08:00",
"latitude": 19.793713,
"longitude": 86.513373,
"tags": [
"enim",
"aliquip",
"qui"
]
}
我们把这些文档存储在一个名为 api 的表中,在一个名为 jdoc 的 jsonb 列中。如果在此列上创建了 GIN 索引,则可以利用该索引进行诸如以下的查询:
-- Find documents in which the key "company" has value "Magnafone"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';
但是,索引无法用于诸如以下的查询,因为尽管运算符 ? 可被索引,但它不会直接应用于已编制索引的列 jdoc:
-- Find documents in which the key "tags" contains key or array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';
即使如此,通过适当使用表达式索引,上面的查询仍可以使用索引。如果查询 "tags" 键内的特定项很常见,那么定义一个这样的索引可能是有价值的:
CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));
现在,_WHERE_子句 _jdoc → 'tags' ? 'qui'_将被识别为可索引运算符 _?_对索引表达式 _jdoc → 'tags'_的一个应用。(可以在 Section 11.7中找到有关表达式索引的更多信息。)
查询的另一种方法是利用包含,例如:
-- Find documents in which the key "tags" contains array element "qui"
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"tags": ["qui"]}';
jdoc 列上的一个简单 GIN 索引可以支持此查询。但请注意,这样一个索引将存储 jdoc 列中的每个键和值的副本,而前一个示例的表达式索引仅存储在 tags 键下找到的数据。虽然简单索引方法要灵活得多(因为它支持针对任何键的查询),但有针对性的表达式索引可能比简单索引更小、更快的搜索速度。
GIN 索引还支持执行 jsonpath 匹配的 @? 和 @@ 运算符。示例为:
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @? '$.tags[*] ? (@ == "qui")';
SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @@ '$.tags[*] == "qui"';
对于这些运算符,GIN索引从 jsonpath 模式中提取 accessors_chain = constant 形式的子句,并根据这些子句中提到的键和值执行索引搜索。访问器链可能包括 ._key_ 、 [], and [_index]_ accessors. The jsonb_ops operator class also supports .* and .* 访问器,但 jsonb_path_ops 运算符类没有。
虽然 jsonb_path_ops 操作符类仅支持带有 @>、@? 和 @@ 操作符的查询,但它比默认操作符类 jsonb_ops 具有显著的性能优势。jsonb_path_ops 索引通常比针对相同数据的 jsonb_ops 索引小得多,并且搜索的特殊性更好,尤其是在查询包含在数据中频繁出现的键时。因此,搜索操作通常比使用默认操作符类时执行得更好。
jsonb_ops 和 jsonb_path_ops GIN索引之间的技术差异在于,前者为数据中的每个键和值创建独立的索引项,而后者仅为数据中的每个值创建索引项。 [7 ]基本上,每个 jsonb_path_ops 索引项都是值和导致该值的键的哈希;例如,要索引 {"foo": {"bar": "baz"}} ,将创建单个索引项,并将三个 foo 、 bar 和 baz 全部合并到哈希值中。因此,寻找此结构的包含查询将导致极其具体的索引搜索;但根本没有办法找出 foo 是否表现为一个键。另一方面, jsonb_ops 索引将创建分别表示 foo 、 bar 和 baz 的三个索引项;然后执行包含查询,它将查找包含这三个项的所有行。虽然GIN索引可以相当高效地执行这样的AND搜索,但它仍然不如等效的 jsonb_path_ops 搜索具体且速度慢,尤其是如果包含任何三个索引项之一的大量行时。
jsonb_path_ops 方法的一个缺点是,它不会为不包含任何值的 JSON 结构(例如 {"a": {}})生成索引条目。如果请求搜索包含此类结构的文档,则需要进行全索引扫描,这非常慢。因此,jsonb_path_ops 不适用于经常执行此类搜索的应用程序。
jsonb 还支持 btree 和 hash 索引。这些通常仅在检查完整 JSON 文档的相等性很重要时才有用。jsonb 数据项的 btree 排序很少受到关注,但为了完整性,它是:
Object > Array > Boolean > Number > String > Null
Object with n pairs > object with n - 1 pairs
Array with n elements > array with n - 1 elements
具有相等对数的对象按以下顺序进行比较:
key-1, value-1, key-2 ...
请注意,对象键按其存储顺序进行比较;特别是,由于较短的键存储在较长键之前,这可能导致不直观的结果,例如:
{ "aa": 1, "c": 1} > {"b": 1, "d": 1}
类似地,具有相等元素数量的数组按以下顺序进行比较:
element-1, element-2 ...
使用与底层 PostgreSQL 数据类型相同的比较规则比较原始 JSON 值。字符串使用默认数据库排序规则进行比较。
8.14.5. jsonb Subscripting #
jsonb 数据类型支持数组式下标表达式,以提取和修改元素。嵌套值可以通过链接下标表达式来表示,遵循与 jsonb_set 函数中的 path 参数相同的规则。如果 jsonb 值是一个数组,则数字下标从零开始,负整数从数组的最后一个元素向后计数。不支持切片表达式。下标表达式的结果始终为 jsonb 数据类型。
UPDATE_语句可以在 _SET_子句中使用下标修改 _jsonb_值。对于所有受影响的值,只要它们存在,就必须能够遍历下标路径。例如,如果每个 _val、val['a']_和 _val['a']['b']_都是对象,则路径 _val['a']['b']['c']_可以一直遍历到 _c。如果任何 val['a']_或 _val['a']['b']_没有定义,它将被创建为一个空对象并根据需要填充。然而,如果任何 _val_本身或其中间值被定义为非对象,例如字符串、数字或 _jsonb__null,则无法进行遍历,因此会引发错误并中止事务。
下标语法的示例:
-- Extract object value by key
SELECT ('{"a": 1}'::jsonb)['a'];
-- Extract nested object value by key path
SELECT ('{"a": {"b": {"c": 1}}}'::jsonb)['a']['b']['c'];
-- Extract array element by index
SELECT ('[1, "2", null]'::jsonb)[1];
-- Update object value by key. Note the quotes around '1': the assigned
-- value must be of the jsonb type as well
UPDATE table_name SET jsonb_field['key'] = '1';
-- This will raise an error if any record's jsonb_field['a']['b'] is something
-- other than an object. For example, the value {"a": 1} has a numeric value
-- of the key 'a'.
UPDATE table_name SET jsonb_field['a']['b']['c'] = '1';
-- Filter records using a WHERE clause with subscripting. Since the result of
-- subscripting is jsonb, the value we compare it against must also be jsonb.
-- The double quotes make "value" also a valid jsonb string.
SELECT * FROM table_name WHERE jsonb_field['key'] = '"value"';
通过下标进行 jsonb 赋值以不同于 jsonb_set 的方式处理一些边缘情况。当源 jsonb 值为 NULL 时,通过下标进行赋值将进行,就像它是下标键暗示的类型(对象或数组)的空 JSON 值:
-- Where jsonb_field was NULL, it is now {"a": 1}
UPDATE table_name SET jsonb_field['a'] = '1';
-- Where jsonb_field was NULL, it is now [1]
UPDATE table_name SET jsonb_field[0] = '1';
如果为包含的元素太少的数组指定索引,则 NULL 元素将附加,直到达到索引并且可以设置值。
-- Where jsonb_field was [], it is now [null, null, 2];
-- where jsonb_field was [0], it is now [0, null, 2]
UPDATE table_name SET jsonb_field[2] = '2';
只要要遍历的最后一个现有元素是一个对象或数组(由相应的下标暗示),jsonb 值就会接受对不存在的下标路径的赋值(路径中最后一个下标指示的元素未遍历,可以是任何内容)。嵌套数组和对象结构将被创建,并且在前一种情况下,null 填充,如下标路径所示,直到可以放置赋值值。
-- Where jsonb_field was {}, it is now {"a": [{"b": 1}]}
UPDATE table_name SET jsonb_field['a'][0]['b'] = '1';
-- Where jsonb_field was [], it is now [null, {"a": 1}]
UPDATE table_name SET jsonb_field[1]['a'] = '1';
8.14.6. Transforms #
有多个附加扩展来实现针对不同过程语言的 jsonb 类型的转换。
PL/Perl 的扩展称为 jsonb_plperl 和 jsonb_plperlu。如果使用它们,jsonb 值将分别映射到 Perl 数组、哈希和标量。
PL/Python 的扩展称为 jsonb_plpython3u。如果使用它,jsonb 值将分别映射到 Python 字典、列表和标量。
在这些扩展中,jsonb_plperl 被认为是“受信任的”,即它可以由在当前数据库上具有 CREATE 权限的非超级用户安装。其余需要超级用户权限才能安装。
8.14.7. jsonpath Type #
jsonpath 类型实现对 PostgreSQL 中 SQL/JSON 路径语言的支持,以有效地查询 JSON 数据。它提供了已解析 SQL/JSON 路径表达式的二进制表示形式,该表示形式指定了路径引擎应从 JSON 数据中检索的项目,以便使用 SQL/JSON 查询函数进行进一步处理。
SQL/JSON 路径谓词和运算符的语义通常遵循 SQL。同时,为了提供处理 JSON 数据的自然方式,SQL/JSON 路径语法使用了一些 JavaScript 约定:
SQL/JSON 路径表达式中的数字文字遵循 JavaScript 规则,这在一些小细节上与 SQL 和 JSON 都不同。例如,SQL/JSON 路径允许 .1 和 1.,而这在 JSON 中无效。例如,支持非十进制整数文字和下划线分隔符, 1_000_000,0x1EEE_FFFF,0o273,0b100101。在 SQL/JSON 路径(以及 JavaScript 中,但不是在 SQL 本身中),基数前缀之后一定不能紧跟下划线分隔符。
SQL/JSON路径表达式通常以SQL字符字符串文本形式写在SQL查询中,因此必须用单引号引起来,并且值中所需的任何单引号都必须加倍(请参阅 Section 4.1.2.1 )。某些形式的路径表达式需要它们内部的字符串文本。这些嵌入的字符串文本遵循JavaScript/ECMAScript惯例:它们必须用双引号引起来,可以在其中使用反斜杠转义来表示难以输入的字符。特别是,在嵌入式字符串文本中编写双引号的方式是 \" ,而要写入反斜杠本身,必须编写 \\ 。其他特殊反斜杠序列包括JavaScript字符串中识别的序列: \b 、 \f 、 \n 、 \r 、 \t 、 \v 用于各种ASCII控制字符, \x_NN for a character code written with only two hex digits, \u_NNNN for a Unicode character identified by its 4-hex-digit code point, and \u{_N… _ 用于使用1到6个十六进制数字编写的Unicode字符代码点。
路径表达式由一系列路径元素组成,这些路径元素可以是以下任何一项:
有关将 jsonpath 表达式与 SQL/JSON 查询函数配合使用的详细信息,请参阅 Section 9.16.2。
Table 8.24. jsonpath Variables
Variable |
Description |
$ |
表示正在查询的JSON值( context item )的变量。 |
$varname |
命名变量。其值可由几个JSON处理函数的参数 vars 设置;有关详细内容,请参见 Table 9.49 。 |
@ |
表示过滤表达式中路径评估结果的变量。 |
Table 8.25. jsonpath Accessors
Accessor Operator |
Description |
._key_ ."$_varname"_ |
返回具有指定键的对象成员的成员访问器。如果键名与从 $ 开始的某个命名变量匹配,或者不满足标识符的 JavaScript 规则,则必须将其用双引号引起来使其成为字符串文字。 |
.* |
返回位于当前对象的顶层的全部成员的值的通配符成员访问器。 |
.** |
返回当前对象的 JSON 层次结构的所有级别的全部成员值(不考虑其嵌套级别)的递归通配符成员访问器。这是 SQL/JSON 标准的 PostgreSQL 扩展。 |
.{_level}_ .{_start_level to end_level}_ |
与 .** 类似,但只选择 JSON 层次结构的指定级别。嵌套级别指定为整数。等级零对应于当前对象。要访问最低嵌套级别,可以使用 last 关键字。这是 SQL/JSON 标准的 PostgreSQL 扩展。 |
[_subscript, …]_ |
数组元素访问器。 subscript 可以用两种形式给出: index 或 start_index to end_index 。第一种形式按其索引返回值的单个数组元素。第二种形式通过索引范围返回值的数组切片,其中包括与提供的 start_index 和 end_index 相对应的元素。指定的 index 可以是整数,也可以是返回值的单个数字表达式,该表达式自动转换为整数。零索引对应于第一个数组元素。你还可以使用 last 关键字来表示最后一个数组元素,这对于处理长度未知的数组很有用。 |
[*] |
返回所有数组元素的通配符数组元素访问器。 |
[7 ]出于此目的,术语“值”包括数组元素,尽管JSON术语有时认为数组元素不同于对象中的值。