PostgreSQL JSON 函數(shù)和操作符

2021-08-27 10:18 更新
9.16.1. 處理和創(chuàng)建JSON數(shù)據(jù)
9.16.2. SQL/JSON 路徑語言

本節(jié)描述:

  • 用于處理和創(chuàng)建JSON數(shù)據(jù)的函數(shù)和運(yùn)算器

  • SQL/JSON路徑語言

要了解有關(guān)SQL/JSON標(biāo)準(zhǔn)的更多信息,請參閱[sqltr-19075-6]。有關(guān)PostgreSQL中支持的JSON類型的詳細(xì)信息,見 第 8.14 節(jié)。 .

9.16.1. 處理和創(chuàng)建JSON數(shù)據(jù)

表 9.44展示了可以用于 JSON 數(shù)據(jù)類型(見第 8.14 節(jié))的操作符。 此外,表 9.1所示的常用比較操作符也適用于jsonb,但不適用于json。 比較操作符遵循 第 8.14.4 節(jié)中的B樹操作概要的排序規(guī)則。

表 9.44. jsonjsonb 操作符

操作符

描述

例子

json -> integerjson

jsonb -> integerjsonb

提取JSON數(shù)組的第n個元素(數(shù)組元素從0開始索引,但負(fù)整數(shù)從末尾開始計數(shù))。

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2{"c":"baz"}

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -3{"a":"foo"}

json -> textjson

jsonb -> textjsonb

用給定的鍵提取JSON對象字段。

'{"a": {"b":"foo"}}'::json -> 'a'{"b":"foo"}

json ->> integertext

jsonb ->> integertext

提取JSON數(shù)組的第n個元素,作為text

'[1,2,3]'::json ->> 23

json ->> texttext

jsonb ->> texttext

用給定的鍵提取JSON對象字段,作為text。

'{"a":1,"b":2}'::json ->> 'b'2

json #> text[]json

jsonb #> text[]jsonb

提取指定路徑下的JSON子對象,路徑元素可以是字段鍵或數(shù)組索引。

'{"a": {"b": ["foo","bar"]}}'::json #> '{a,b,1}'"bar"

json #>> text[]text

jsonb #>> text[]text

將指定路徑上的JSON子對象提取為text

'{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}'bar


注意

如果JSON輸入沒有匹配請求的正確結(jié)構(gòu),字段/元素/路徑提取操作符返回NULL,而不是失敗;例如,如果不存在這樣的鍵或數(shù)組元素。

還有一些操作符僅適用于jsonb,如表表 9.45所示。 第第 8.14.4 節(jié)描述了如何使用這些操作符來有效地搜索索引的 jsonb數(shù)據(jù)。

表 9.45. 附加的 jsonb 操作符

操作符

描述

例子

jsonb @> jsonbboolean

第一個JSON值是否包含第二個?(請參見第 8.14.3 節(jié)以了解包含的詳細(xì)信息。)

'{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonbt

jsonb <@ jsonbboolean

第二個JSON中是否包含第一個JSON值?

'{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonbt

jsonb ? textboolean

文本字符串是否作為JSON值中的頂級鍵或數(shù)組元素存在?

'{"a":1, "b":2}'::jsonb ? 'b't

'["a", "b", "c"]'::jsonb ? 'b't

jsonb ?| text[]boolean

文本數(shù)組中的字符串是否作為頂級鍵或數(shù)組元素存在?

'{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'd']t

jsonb ?& text[]boolean

文本數(shù)組中的所有字符串都作為頂級鍵或數(shù)組元素存在嗎?

'["a", "b", "c"]'::jsonb ?& array['a', 'b']t

jsonb || jsonbjsonb

連接兩個jsonb值。連接兩個數(shù)組將生成一個包含每個輸入的所有元素的數(shù)組。連接兩個對象將生成一個包含它們鍵的并集的對象,當(dāng)存在重復(fù)的鍵時取第二個對象的值。 所有其他情況都是通過將非數(shù)組輸入轉(zhuǎn)換為單個元素數(shù)組,然后按照兩個數(shù)組的方式進(jìn)行處理。 不遞歸操作:只有頂級數(shù)組或?qū)ο蠼Y(jié)構(gòu)被合并。

'["a", "b"]'::jsonb || '["a", "d"]'::jsonb["a", "b", "a", "d"]

'{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb{"a": "b", "c": "d"}

jsonb - textjsonb

從JSON對象中刪除鍵(以及它的值),或從JSON數(shù)組中刪除匹配的字符串值。

'{"a": "b", "c": "d"}'::jsonb - 'a'{"c": "d"}

'["a", "b", "c", "b"]'::jsonb - 'b'["a", "c"]

jsonb - text[]jsonb

從左操作數(shù)中刪除所有匹配的鍵或數(shù)組元素。

'{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]{}

jsonb - integerjsonb

刪除具有指定索引的數(shù)組元素(負(fù)整數(shù)從末尾計數(shù))。如果JSON值不是數(shù)組,則拋出錯誤。

'["a", "b"]'::jsonb - 1 ["a"]

jsonb #- text[]jsonb

刪除指定路徑上的字段或數(shù)組元素,路徑元素可以是字段鍵或數(shù)組索引。

'["a", {"b":1}]'::jsonb #- '{1,b}'["a", {}]

jsonb @? jsonpathboolean

JSON路徑是否為指定的JSON值返回任何項?

'{"a":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)'t

jsonb @@ jsonpathboolean

返回指定JSON值的JSON路徑謂詞檢查的結(jié)果。只考慮結(jié)果的第一項。如果結(jié)果不是布爾值,則返回NULL。

'{"a":[1,2,3,4,5]}'::jsonb @@ '$.a[*] > 2't


注意

jsonpath操作符@?@@抑制以下錯誤:缺少對象字段或數(shù)組元素,意外的JSON項目類型,日期時間和數(shù)字錯誤。 還可以告訴以下描述的與jsonpath相關(guān)的函數(shù)來抑制這些類型的錯誤。在搜索不同結(jié)構(gòu)的JSON文檔集合時,此行為可能會有所幫助。 The jsonpath operators @?and @@ suppress the following errors: missing object field or array element, unexpected JSON item type, datetime and numeric errors. The jsonpath-related functions described below can also be told to suppress these types of errors. This behavior might be helpful when searching JSON document collections of varying structure.

表 9.46 顯示可用于構(gòu)造jsonjsonb值的函數(shù)。

表 9.46. JSON 創(chuàng)建函數(shù)

函數(shù)

描述

例子

to_json ( anyelement ) → json

to_jsonb ( anyelement ) → jsonb

將任何SQL值轉(zhuǎn)換為jsonjsonb。數(shù)組和組合遞歸地轉(zhuǎn)換為數(shù)組和對象(多維數(shù)組在JSON中變成數(shù)組的數(shù)組)。 否則,如果存在從SQL數(shù)據(jù)類型到json的類型轉(zhuǎn)換,則造型函數(shù)將用于執(zhí)行轉(zhuǎn)換; [a] 否則,將生成一個標(biāo)量json值。對于除數(shù)字、布爾值或空值之外的任何標(biāo)量,將使用文本表示,并根據(jù)需要進(jìn)行轉(zhuǎn)義,使其成為有效的JSON字符串值。

to_json('Fred said "Hi."'::text)"Fred said \"Hi.\""

to_jsonb(row(42, 'Fred said "Hi."'::text)){"f1": 42, "f2": "Fred said \"Hi.\""}

array_to_json ( anyarray [, boolean ] ) → json

將SQL數(shù)組轉(zhuǎn)換為JSON數(shù)組。該行為與to_json相同,只是如果可選boolean參數(shù)為真,換行符將在頂級數(shù)組元素之間添加。

array_to_json('{{1,5},{99,100}}'::int[])[[1,5],[99,100]]

row_to_json ( record [, boolean ] ) → json

將SQL組合值轉(zhuǎn)換為JSON對象。該行為與to_json相同,只是如果可選boolean參數(shù)為真,換行符將在頂級元素之間添加。

row_to_json(row(1,'foo')){"f1":1,"f2":"foo"}

json_build_array ( VARIADIC "any" ) → json

jsonb_build_array ( VARIADIC "any" ) → jsonb

根據(jù)可變參數(shù)列表構(gòu)建可能異構(gòu)類型的JSON數(shù)組。每個參數(shù)都按照to_jsonto_jsonb進(jìn)行轉(zhuǎn)換。

json_build_array(1, 2, 'foo', 4, 5)[1, 2, "foo", 4, 5]

json_build_object ( VARIADIC "any" ) → json

jsonb_build_object ( VARIADIC "any" ) → jsonb

根據(jù)可變參數(shù)列表構(gòu)建一個JSON對象。按照慣例,參數(shù)列表由交替的鍵和值組成。 關(guān)鍵參數(shù)強(qiáng)制轉(zhuǎn)換為文本;值參數(shù)按照to_jsonto_jsonb進(jìn)行轉(zhuǎn)換。

json_build_object('foo', 1, 2, row(3,'bar')){"foo" : 1, "2" : {"f1":3,"f2":"bar"}}

json_object ( text[] ) → json

jsonb_object ( text[] ) → jsonb

從文本數(shù)組構(gòu)建JSON對象。該數(shù)組必須有兩個維度,一個維度的成員數(shù)為偶數(shù),在這種情況下,它們被視為交替的鍵/值對; 另一個維度的成員數(shù)為二維,每個內(nèi)部數(shù)組恰好有兩個元素,它們被視為鍵/值對。所有值都轉(zhuǎn)換為JSON字符串。

json_object('{a, 1, b, "def", c, 3.5}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object('{{a, 1}, {b, "def"}, {c, 3.5}}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object ( keys text[], values text[] ) → json

jsonb_object ( keys text[], values text[] ) → jsonb

這種形式的json_object從單獨(dú)的文本數(shù)組中成對地獲取鍵和值。否則,它與單參數(shù)形式相同。

json_object('{a,b}', '{1,2}'){"a": "1", "b": "2"}

[a] 例如,hstore擴(kuò)展有一個從hstorejson的轉(zhuǎn)換,這樣通過json創(chuàng)建函數(shù)轉(zhuǎn)換的 hstore值將被表示為json對象,而不是原始字符串值


表 9.47 顯示可用于處理jsonjsonb值的函數(shù)。

表 9.47. JSON 處理函數(shù)

函數(shù)

描述

例子

json_array_elements ( json ) → setof json

jsonb_array_elements ( jsonb ) → setof jsonb

將頂級JSON數(shù)組展開為一組JSON值。

select * from json_array_elements('[1,true, [2,false]]')

   value
-----------
 1
 true
 [2,false]

json_array_elements_text ( json ) → setof text

jsonb_array_elements_text ( jsonb ) → setof text

將頂級JSON數(shù)組展開為一組文本值。

select * from json_array_elements_text('["foo", "bar"]')

   value
-----------
 foo
 bar

json_array_length ( json ) → integer

jsonb_array_length ( jsonb ) → integer

返回頂級JSON數(shù)組中的元素數(shù)量。

json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]')5

json_each ( json ) → setof record ( key text, value json )

jsonb_each ( jsonb ) → setof record ( key text, value jsonb)

將頂級JSON對象展開為一組鍵/值對。

select * from json_each('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | "foo"
 b   | "bar"

json_each_text ( json ) → setof record ( key text, value text)

jsonb_each_text ( jsonb ) → setof record ( key text, value text)

將頂級JSON對象擴(kuò)展為一組鍵/值對。返回的的類型為文本。

select * from json_each_text('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | foo
 b   | bar

json_extract_path ( from_json json, VARIADIC path_elems text[] ) → json

jsonb_extract_path ( from_json jsonb, VARIADIC path_elems text[] ) → jsonb

在指定路徑下提取JSON子對象。(這在功能上相當(dāng)于#>操作符,但在某些情況下,將路徑寫成可變參數(shù)列表會更方便。)

json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')"foo"

json_extract_path_text ( from_json json, VARIADIC path_elems text[] ) → text

jsonb_extract_path_text ( from_json jsonb, VARIADIC path_elems text[] ) → text

將指定路徑上的JSON子對象提取為文本。(這在功能上等同于#>>操作符。)

json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')foo

json_object_keys ( json ) → setof text

jsonb_object_keys ( jsonb ) → setof text

返回頂級JSON對象中的鍵集合。

select * from json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')

 json_object_keys
------------------
 f1
 f2

json_populate_record ( base anyelement, from_json json ) → anyelement

jsonb_populate_record ( base anyelement, from_json jsonb ) → anyelement

將頂級JSON對象擴(kuò)展為具有基本參數(shù)的復(fù)合類型的行。JSON對象將被掃描,查找名稱與輸出行類型的列名匹配的字段,并將它們的值插入到輸出的這些列中。 (不對應(yīng)任何輸出列名的字段將被忽略。)在典型的使用中,基本的值僅為NULL,這意味著任何不匹配任何對象字段的輸出列都將被填充為空。 但是,如果 base 不為NULL,那么它包含的值將用于不匹配的列。

要將JSON值轉(zhuǎn)換為輸出列的SQL類型,需要按次序應(yīng)用以下規(guī)則:

  • 在所有情況下,JSON空值都會轉(zhuǎn)換為SQL空值。

  • 如果輸出列的類型是jsonjsonb,則會精確地重制JSON值。

  • 如果輸出列是復(fù)合(行)類型,且JSON值是JSON對象,則該對象的字段將轉(zhuǎn)換為輸出行類型的列,通過這些規(guī)則的遞歸應(yīng)用程序。

  • 同樣,如果輸出列是數(shù)組類型,而JSON值是JSON數(shù)組,則通過這些規(guī)則的遞歸應(yīng)用程序?qū)SON數(shù)組的元素轉(zhuǎn)換為輸出數(shù)組的元素。

  • 否則,如果JSON值是字符串,則將字符串的內(nèi)容提供給輸入轉(zhuǎn)換函數(shù),用以確定列的數(shù)據(jù)類型。

  • 否則,JSON值的普通文本表示將被提供給輸入轉(zhuǎn)換函數(shù),以確定列的數(shù)據(jù)類型。

雖然下面的示例使用一個常量JSON值,典型的用法是在查詢的FROM子句中從另一個表側(cè)面地引用jsonjsonb列。 在FROM子句中編寫json_populate_record是一種很好的實踐,因為提取的所有列都可以使用,而不需要重復(fù)的函數(shù)調(diào)用。

create type subrowtype as (d int, e text); create type myrowtype as (a int, b text[], c subrowtype);

select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}, "x": "foo"}')

 a |   b       |      c
---+-----------+-------------
 1 | {2,"a b"} | (4,"a b c")

json_populate_recordset ( base anyelement, from_json json ) → setof anyelement

jsonb_populate_recordset ( base anyelement, from_json jsonb ) → setof anyelement

將對象的頂級JSON數(shù)組展開為一組具有基本參數(shù)的復(fù)合類型的行。 對于json[b]_populate_record,將如上所述處理JSON數(shù)組的每個元素。

create type twoints as (a int, b int);

select * from json_populate_recordset(null::twoints, '[{"a":1,"b":2}, {"a":3,"b":4}]')

 a | b
---+---
 1 | 2
 3 | 4

json_to_record ( json ) → record

jsonb_to_record ( jsonb ) → record

將頂級JSON對象展開為具有由 AS子句定義的復(fù)合類型的行。 (與所有返回record的函數(shù)一樣,調(diào)用查詢必須使用AS子句顯式定義記錄的結(jié)構(gòu)。) 輸出記錄由JSON對象的字段填充,與上面描述的json[b]_populate_record的方式相同。 由于沒有輸入記錄值,不匹配的列總是用空值填充。

create type myrowtype as (a int, b text);

select * from json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as 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_to_recordset ( json ) → setof record

jsonb_to_recordset ( jsonb ) → setof record

將頂級JSON對象數(shù)組展開為一組由AS子句定義的復(fù)合類型的行。 (與所有返回record的函數(shù)一樣,調(diào)用查詢必須使用AS子句顯式定義記錄的結(jié)構(gòu)。) 對于json[b]_populate_record,將如上所述處理JSON數(shù)組的每個元素。

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[], new_value jsonb[, create_if_missing boolean ] ) → jsonb

返回target,將path指定的項替換為new_value, 如果create_if_missing為真(此為默認(rèn)值)并且path指定的項不存在,則添加 new_value 。 路徑中的所有前面步驟都必須存在,否則將不加改變地返回target。 與面向路徑操作符一樣,負(fù)整數(shù)出現(xiàn)在JSON數(shù)組末尾的path計數(shù)中。 如果最后一個路徑步驟是超出范圍的數(shù)組索引,并且create_if_missing為真,那么如果索引為負(fù),新值將添加到數(shù)組的開頭,如果索引為正,則添加到數(shù)組的結(jié)尾。

jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', false)[{"f1": [2, 3, 4], "f2": null}, 2, null, 3]

jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]')[{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]

jsonb_set_lax ( target jsonb, path text[], new_value jsonb[, create_if_missing boolean [, null_value_treatment text ]] ) → jsonb

如果new_value不為NULL,則行為與jsonb_set完全一樣。 否則,根據(jù)null_value_treatment的值,它必須是'raise_exception''use_json_null', 'delete_key', 或'return_target'。 默認(rèn)值為'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": null}, 2]

jsonb_insert ( target jsonb, path text[], new_value jsonb[, insert_after boolean ] ) → jsonb

返回插入new_valuetarget。 如果path指派的項是一個數(shù)組元素,如果 insert_after為假(此為默認(rèn)值),則new_value將被插入到該項之前,如果 insert_after 為真則在該項之后。 如果由path指派的項是一個對象字段,則只在對象不包含該鍵時才插入 new_value。 路徑中的所有前面步驟都必須存在,否則將不加改變地返回target。 與面向路徑操作符一樣,負(fù)整數(shù)出現(xiàn)在JSON數(shù)組末尾的 path計數(shù)中。 如果最后一個路徑步驟是超出范圍的數(shù)組下標(biāo),則如果下標(biāo)為負(fù),則將新值添加到數(shù)組的開頭;如果下標(biāo)為正,則將新值添加到數(shù)組的結(jié)尾。

jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"'){"a": [0, "new_value", 1, 2]}

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 ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

檢查JSON路徑是否返回指定JSON值的任何項。如果指定了vars參數(shù),則它必須是一個JSON對象,并且它的字段提供要替換到jsonpath表達(dá)式中的名稱值。 如果指定了silent參數(shù)并為true,函數(shù)會抑制與@?@@運(yùn)算符相同的錯誤。

jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')t

jsonb_path_match ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

返回指定JSON值的JSON路徑謂詞檢查的結(jié)果。只有結(jié)果的第一項被考慮在內(nèi)。 如果結(jié)果不是布爾值,則返回NULL。可選的varssilent參數(shù)的作用與jsonb_path_exists相同。

jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2, "max":4}')t

jsonb_path_query ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

為指定的JSON值返回由JSON路徑返回的所有JSON項??蛇x的varssilent參數(shù)的作用與jsonb_path_exists相同。

select * from jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')

 jsonb_path_query
------------------
 2
 3
 4

jsonb_path_query_array ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

以JSON數(shù)組的形式返回由JSON路徑為指定的JSON值返回的所有JSON項??蛇x的varssilent參數(shù)的作用與jsonb_path_exists相同。

jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')[2, 3, 4]

jsonb_path_query_first ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

為指定的JSON值返回由JSON路徑返回的第一個JSON項。如果沒有結(jié)果則返回NULL。 可選的varssilent參數(shù)的作用與 jsonb_path_exists相同。

jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')2

jsonb_path_exists_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_match_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_query_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

jsonb_path_query_array_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

jsonb_path_query_first_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

這些函數(shù)與上面描述的沒有_tz后綴的對應(yīng)函數(shù)類似,除了這些函數(shù)支持需要時區(qū)感知轉(zhuǎn)換的日期/時間值比較之外。 下面的示例需要將只包含日期的值2015-08-02解釋為帶有時區(qū)的時間戳,因此結(jié)果依賴于當(dāng)前TimeZone設(shè)置。 由于這種依賴性,這些函數(shù)被標(biāo)記為穩(wěn)定的,這意味著不能在索引中使用這些函數(shù)。 它們的對應(yīng)項是不可改變的,因此可以用于索引;但是,如果要求他們進(jìn)行這樣的比較,他們就會拋出錯誤。

jsonb_path_exists_tz('["2015-08-01 12:00:00 -05"]', '$[*] ? (@.datetime() < "2015-08-02".datetime())')t

jsonb_pretty ( jsonb ) → text

將給定的JSON值轉(zhuǎn)換為精美打印的,縮進(jìn)的文本。

jsonb_pretty('[{"f1":1,"f2":null}, 2]')

[
    {
        "f1": 1,
        "f2": null
    },
    2
]

json_typeof ( json ) → text

jsonb_typeof ( jsonb ) → text

以文本字符串形式返回頂級JSON值的類型??赡艿念愋陀?code class="literal">object, array,string, number,boolean, 和 null。 ( null的結(jié)果不應(yīng)該與SQL NULL 混淆;參見示例。)

json_typeof('-123.4')number

json_typeof('null'::json)null

json_typeof(NULL::json) IS NULLt


參見 第 9.21 節(jié),聚合函數(shù)json_agg將聚合記錄值為JSON,聚合函數(shù)json_object_agg將聚合成對的值為JSON對象, 以及它們在jsonb中的相當(dāng)?shù)?函數(shù)), jsonb_aggjsonb_object_agg。

9.16.2. SQL/JSON 路徑語言

SQL/JSON路徑表達(dá)式指定了要從JSON數(shù)據(jù)中檢索的項目,類似于SQL訪問XML時使用的XPath表達(dá)式。 在PostgreSQL中,路徑表達(dá)式作為jsonpath數(shù)據(jù)類型實現(xiàn),可以使用第 8.14.6 節(jié)中描述的任何元素。

JSON查詢函數(shù)和操作符將提供的路徑表達(dá)式傳遞給path engine進(jìn)行評估。 如果表達(dá)式與被查詢的JSON數(shù)據(jù)匹配,則返回相應(yīng)的JSON項或項集。 路徑表達(dá)式是用SQL/JSON路徑語言編寫的,也可以包括算術(shù)表達(dá)式和函數(shù)。

路徑表達(dá)式由jsonpath數(shù)據(jù)類型允許的元素序列組成。路徑表達(dá)式通常從左向右求值,但你可以使用圓括號來更改操作的順序。 如果計算成功,將生成一系列JSON項,并將計算結(jié)果返回到JSON查詢函數(shù),該函數(shù)將完成指定的計算。

要引用正在查詢的JSON值(context item項),在路徑表達(dá)式中使用$變量。 它后面可以跟著一個或多個accessor operators,這些操作符在JSON結(jié)構(gòu)中逐級向下檢索上下文項的子項。 后面的每個操作符處理前一個求值步驟的結(jié)果。

例如,假設(shè)你有一些你想要解析的來自GPS跟蹤器的JSON數(shù)據(jù),例如:

{
  "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
      }
    ]
  }
}

為了檢索可用的軌跡段,你需要使用.key 訪問操作符來向下瀏覽周邊的JSON對象:

$.track.segments

要檢索數(shù)組的內(nèi)容,通常使用[*]操作符。例如,下面的路徑將返回所有可用軌道段的位置坐標(biāo):

$.track.segments[*].location

要只返回第一個段的坐標(biāo),可以在[]訪問操作符中指定相應(yīng)的下標(biāo)。重新調(diào)用相對于0的JSON數(shù)組索引:

$.track.segments[0].location

每個路徑求值步驟的結(jié)果可以由本文中第 9.16.2.2 節(jié)中列出的一個或多個jsonpath操作符和方法來處理。 每個方法名之前必須有一個點。例如,你可以得到一個數(shù)組的大小:

$.track.segments.size()

在路徑表達(dá)式中使用jsonpath操作符和方法的更多示例見下面本文中第 9.16.2.2 節(jié)。

在定義路徑時,還可以使用一個或多個與SQL中的WHERE子句類似的filter expressions。 過濾器表達(dá)式以問號開頭,并在圓括號中提供條件:

? (condition)

過濾表達(dá)式必須在它們應(yīng)該應(yīng)用的路徑求值步驟之后寫入。該步驟的結(jié)果將被篩選,以只包括滿足所提供條件的那些項。 SQL/JSON定義了三值邏輯,因此條件可以是 true, false,或 unknown。 unknown值發(fā)揮與SQL NULL相同的角色,可以使用 is unknown謂詞進(jìn)行測試。 進(jìn)一步的路徑求值步驟只使用篩選器表達(dá)式返回true的那些項。

可以在過濾表達(dá)式中使用的函數(shù)和操作符羅列在表 9.49中。 在一個過濾表達(dá)式中,@變量表示被過濾的值(也就是說,前面路徑步驟的一個結(jié)果)。你可以在 @后面寫訪問操作符來檢索組件項。

例如,假設(shè)你想要檢索所有高于130的心率值。你可以使用下面的表達(dá)式來實現(xiàn)這一點:

$.track.segments[*].HR ? (@ > 130)

為了獲得具有這些值的片段的開始時間,必須在返回開始時間之前過濾掉不相關(guān)的片段,所以過濾表達(dá)式應(yīng)用于上一步,條件中使用的路徑不同:

$.track.segments[*] ? (@.HR > 130)."start time"

如果需要,可以按順序使用幾個過濾器表達(dá)式。例如,下面的表達(dá)式選擇所有包含有相關(guān)坐標(biāo)和高心率值的位置的段的開始時間:

$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"

也允許在不同嵌套層級中使用過濾器表達(dá)式。下面的例子首先根據(jù)位置篩選所有的片段,然后返回這些片段的高心率值,如果適用的話:

$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)

你也可以在彼此之間嵌套過濾器表達(dá)式:

$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()

如果包含任何具有高心率值的片段,則該表達(dá)式返回曲目的大小,否則返回空序列。

PostgreSQL的SQL/JSON路徑語言的實現(xiàn)與SQL/JSON標(biāo)準(zhǔn)有以下偏差:

  • 路徑表達(dá)式可以是布爾謂詞,盡管SQL/JSON標(biāo)準(zhǔn)只允許在過濾器中使用謂詞。 這是實現(xiàn)@@操作符所必需的。例如,下面的jsonpath表達(dá)式在PostgreSQL中是有效的:

    $.track.segments[*].HR < 70
    
  • 在解釋like_regex過濾器中使用的正則表達(dá)式模式方面有一些小的差異,如本文中第 9.16.2.3 節(jié)中所述。

9.16.2.1. 嚴(yán)格的(Strict) 和 不嚴(yán)格的(Lax) 模式

當(dāng)查詢JSON數(shù)據(jù)時,路徑表達(dá)式可能與實際的JSON數(shù)據(jù)結(jié)構(gòu)不匹配。 試圖訪問不存在的對象成員或數(shù)組元素會導(dǎo)致結(jié)構(gòu)錯誤。SQL/JSON路徑表達(dá)式有兩種處理結(jié)構(gòu)錯誤的模式:

  • 不嚴(yán)格的(lax)(默認(rèn))—路徑引擎隱式地將查詢的數(shù)據(jù)適配到指定的路徑。任何剩余的結(jié)構(gòu)錯誤都將被抑制并轉(zhuǎn)換為空SQL/JSON序列。

  • 嚴(yán)格的(strict) —如果發(fā)生了結(jié)構(gòu)錯誤,則會引發(fā)錯誤。

如果JSON數(shù)據(jù)不符合期望的模式,不嚴(yán)格的(lax)模式有助于匹配JSON文檔結(jié)構(gòu)和路徑表達(dá)式。 如果操作不匹配特定操作的要求,可以自動將其包裝為SQL/JSON數(shù)組,也可以在執(zhí)行該操作之前將其元素轉(zhuǎn)換為SQL/JSON序列來解包裝。 此外,比較操作符會自動以lax模式打開它們的操作數(shù),因此你可以開包即用的就能比較SQL/JSON數(shù)組。 大小為1的數(shù)組被認(rèn)為等于它的唯一元素。只有在以下情況下才不會自動展開:

  • 路徑表達(dá)式包含type()size()方法,它們分別返回數(shù)組中的元素類型和數(shù)量。

  • 查詢的JSON數(shù)據(jù)包含嵌套的數(shù)組。在本例中,只有最外層的數(shù)組被打開,而所有內(nèi)部數(shù)組保持不變。 因此,隱式展開在每個路徑求值步驟中只能向下進(jìn)行一級。

例如,當(dāng)查詢上面列出的GPS數(shù)據(jù)時,當(dāng)使用不嚴(yán)格的(lax)模式時,你可以從它存儲了一組片段的事實中抽象出來:

lax $.track.segments.location

在嚴(yán)格的(strict)模式中,指定的路徑必須與查詢的JSON文檔的結(jié)構(gòu)完全匹配才能返回SQL/JSON項,因此使用該路徑表達(dá)式會導(dǎo)致錯誤。 要得到與不嚴(yán)格的(lax)模式相同的結(jié)果,你必須顯式地打開segments數(shù)組:

strict $.track.segments[*].location

9.16.2.2. SQL/JSON 路徑操作符和方法

表 9.48顯示了jsonpath中可用的操作符和方法。 請注意,雖然一元操作符和方法可以應(yīng)用于由前一個路徑步驟產(chǎn)生的多個值,二元操作符(加法等)只能應(yīng)用于單個值。

表 9.48. jsonpath 操作符和方法

操作符/方法

描述

例子

number + numbernumber

加法

jsonb_path_query('[2]', '$[0] + 3')5

+ numbernumber

一元加號(無操作);與加法不同,這個可以迭代多個值

jsonb_path_query_array('{"x": [2,3,4]}', '+ $.x')[2, 3, 4]

number - numbernumber

減法

jsonb_path_query('[2]', '7 - $[0]')5

- numbernumber

否定;與減法不同,它可以迭代多個值

jsonb_path_query_array('{"x": [2,3,4]}', '- $.x')[-2, -3, -4]

number * numbernumber

乘法

jsonb_path_query('[4]', '2 * $[0]')8

number / numbernumber

除法

jsonb_path_query('[8.5]', '$[0] / 2')4.2500000000000000

number % numbernumber

模數(shù) (余數(shù))

jsonb_path_query('[32]', '$[0] % 10')2

value . type()string

JSON項的類型 (參見 json_typeof)

jsonb_path_query_array('[1, "2", {}]', '$[*].type()')["number", "string", "object"]

value . size()number

JSON項的大小(數(shù)組元素的數(shù)量,如果不是數(shù)組則為1)

jsonb_path_query('{"m": [11, 15]}', '$.m.size()')2

value . double()number

從JSON數(shù)字或字符串轉(zhuǎn)換過來的近似浮點數(shù)

jsonb_path_query('{"len": "1.9"}', '$.len.double() * 2')3.8

number . ceiling()number

大于或等于給定數(shù)字的最接近的整數(shù)

jsonb_path_query('{"h": 1.3}', '$.h.ceiling()')2

number . floor()number

小于或等于給定數(shù)字的最近整數(shù)

jsonb_path_query('{"h": 1.7}', '$.h.floor()')1

number . abs()number

給定數(shù)字的絕對值

jsonb_path_query('{"z": -0.3}', '$.z.abs()')0.3

string . datetime()datetime_type (see note)

從字符串轉(zhuǎn)換過來的日期/時間值

jsonb_path_query('["2015-8-1", "2015-08-12"]', '$[*] ? (@.datetime() < "2015-08-2".datetime())')"2015-8-1"

string . datetime(template )datetime_type (see note)

使用指定的to_timestamp模板從字符串轉(zhuǎn)換過來的日期/時間值

jsonb_path_query_array('["12:30", "18:40"]', '$[*].datetime("HH24:MI")')["12:30:00", "18:40:00"]

object . keyvalue()array

對象的鍵值對,表示為包含三個字段的對象數(shù)組:"key", "value",和"id";"id"是鍵值對所歸屬對象的唯一標(biāo)識符

jsonb_path_query_array('{"x": "20", "y": 32}', '$.keyvalue()')[{"id": 0, "key": "x", "value": "20"}, {"id": 0, "key": "y", "value": 32}]


注意

datetime()datetime(template )方法的結(jié)果類型可以是date, timetz, time,timestamptz, 或 timestamp。 這兩個方法都動態(tài)地確定它們的結(jié)果類型。

datetime()方法依次嘗試將其輸入字符串與date, timetz, time,timestamptz, 和 timestamp的ISO格式進(jìn)行匹配。 它在第一個匹配格式時停止,并發(fā)出相應(yīng)的數(shù)據(jù)類型。

datetime(template )方法根據(jù)所提供的模板字符串中使用的字段確定結(jié)果類型。

datetime()datetime(template )方法使用與to_timestamp SQL函數(shù)相同的解析規(guī)則(see 第 9.8 節(jié)),但有三個例外。 首先,這些方法不允許不匹配的模板模式。 其次,模板字符串中只允許以下分隔符:減號、句點、solidus(斜杠)、逗號、撇號、分號、冒號和空格。 第三,模板字符串中的分隔符必須與輸入字符串完全匹配。

如果需要比較不同的日期/時間類型,則應(yīng)用隱式轉(zhuǎn)換。 date值可以轉(zhuǎn)換為timestamptimestamptz, timestamp可以轉(zhuǎn)換為timestamptz, time可以轉(zhuǎn)換為 timetz。 但是,除了第一個轉(zhuǎn)換外,其他所有轉(zhuǎn)換都依賴于當(dāng)前TimeZone設(shè)置,因此只能在時區(qū)感知的jsonpath函數(shù)中執(zhí)行。

表 9.49顯示了適用的過濾器表達(dá)式元素。

表 9.49. jsonpath 過濾器表達(dá)式元素

謂詞/值

描述

例子

value == valueboolean

相等比較(這個,和其他比較操作符,適用于所有JSON標(biāo)量值)

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == 1)')[1, 1]

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == "a")')["a"]

value != valueboolean

value <> valueboolean

不相等比較

jsonb_path_query_array('[1, 2, 1, 3]', '$[*] ? (@ != 1)')[2, 3]

jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <> "b")')["a", "c"]

value < valueboolean

小于比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ < 2)')[1]

value <= valueboolean

小于或等于比較

jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <= "b")')["a", "b"]

value > valueboolean

大于比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ > 2)')[3]

value >= valueboolean

大于或等于比較

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ >= 2)')[2, 3]

trueboolean

JSON常數(shù)

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == true)'){"name": "Chris", "parent": true}

falseboolean

JSON常數(shù)

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == false)'){"name": "John", "parent": false}

nullvalue

JSON常數(shù)null(注意,與SQL不同,與null比較可以正常工作)

jsonb_path_query('[{"name": "Mary", "job": null}, {"name": "Michael", "job": "driver"}]', '$[*] ? (@.job == null) .name')"Mary"

boolean && booleanboolean

布爾 AND

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ > 1 && @ < 5)')3

boolean || booleanboolean

布爾 OR

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)')7

! booleanboolean

布爾 NOT

jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))')7

boolean is unknownboolean

測試布爾條件是否為 unknown。

jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) is unknown)')"foo"

string like_regex string [ flag string ] → boolean

測試第一個操作數(shù)是否與第二個操作數(shù)給出的正則表達(dá)式匹配,可選使用由一串flag字符描述的修改(參見本文中第 9.16.2.3 節(jié))。

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"]

string starts with stringboolean

測試第二個操作數(shù)是否為第一個操作數(shù)的初始子串。

jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@ starts with "John")')"John Smith"

exists ( path_expression )boolean

測試路徑表達(dá)式是否至少匹配一個SQL/JSON項。 如果路徑表達(dá)式會導(dǎo)致錯誤,則返回unknown;第二個例子使用這個方法來避免在嚴(yán)格模式下出現(xiàn)無此鍵(no-such-key)錯誤。

jsonb_path_query('{"x": [1, 2], "y": [2, 4]}', 'strict $.* ? (exists (@ ? (@[*] > 2)))')[2, 4]

jsonb_path_query_array('{"value": 41}', 'strict $ ? (exists (@.name)) .name')[]


9.16.2.3. SQL/JSON 正則表達(dá)式

SQL/JSON路徑表達(dá)式允許通過like_regex過濾器將文本匹配為正則表達(dá)式。 例如,下面的SQL/JSON路徑查詢將不區(qū)分大小寫地匹配以英語元音開頭的數(shù)組中的所有字符串:

$[*] ? (@ like_regex "^[aeiou]" flag "i")

可選的flag字符串可以包括一個或多個字符i用于不區(qū)分大小寫的匹配,m允許^$在換行時匹配,s允許.匹配換行符, q引用整個模式(將行為簡化為一個簡單的子字符串匹配)。

SQL/JSON標(biāo)準(zhǔn)借用了來自LIKE_REGEX操作符的正則表達(dá)式定義,其使用了XQuery標(biāo)準(zhǔn)。 PostgreSQL目前不支持LIKE_REGEX操作符。因此,like_regex過濾器是使用第 9.7.3 節(jié)中描述的POSIX正則表達(dá)式引擎來實現(xiàn)的。 這導(dǎo)致了與標(biāo)準(zhǔn)SQL/JSON行為的各種細(xì)微差異,這在第 9.7.3.8 節(jié)中進(jìn)行了分類。 但是請注意,這里描述的標(biāo)志字母不兼容并不適用于SQL/JSON,因為它將XQuery標(biāo)志字母翻譯為符合POSIX引擎的預(yù)期。

請記住,like_regex的模式參數(shù)是一個JSON路徑字符串文字,根據(jù)第 8.14.6 節(jié)給出的規(guī)則編寫。 這特別意味著在正則表達(dá)式中要使用的任何反斜杠都必須加倍。例如,匹配只包含數(shù)字的字符串:

$ ? (@ like_regex "^\\d+$")


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號