Postgresql中JSON数据构造与操作符实例

2022-11-21 09:56:06 浏览数 (1)

JSON数据构造方法

注意:区分数字与文本。

  • 这是数字:'0.1'::json
  • 这是文本:'"0.1"'::json
  • 1是数组,3是文本:'[1, "3"]'::jsonb

注意:区分数据的三种形态。

  • 这是单独数据:'1'::json
  • 这是数组里面的数据:'[1]'::json
  • 这是object里面的数据:'{"abc":1}'::json
代码语言:javascript复制
-- 可以为字符串,必须用双引号
SELECT '"abc"'::json;			-- OK
 json  
-------
 "abc"
 
-- 可以为数字
SELECT '0.1'::json;				-- OK
 json 
------
 0.1
 
SELECT '1e100'::json;			-- OK
 json  
-------
 1e100

-- 可以为true/false/null
SELECT ' true '::json;			-- OK, even with extra whitespace
  json  
--------
  true 
 
-- 可以为数组
SELECT '[]'::json;				-- OK
 json 
------
 []
 
SELECT '[1,2]'::json;			-- OK
 json  
-------
 [1,2]
 
-- 可以为Objects:{key:value}
SELECT '{}'::json;				-- OK
 json 
------
 {}
 
SELECT '{"abc":1}'::json;		-- OK
   json    
-----------
 {"abc":1}
 
 
-- 可以嵌套
SELECT '{"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}'::json; -- OK
                          json                           
---------------------------------------------------------
 {"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}

JSON操作符与实例

  • JSON与JSONB的差别在存储上,JSON直接保存文本不做任何解析;JSONB在输入后自动解析记录二进制信息。在使用时JSONB省去了解析的步骤,使用时效率更高;JSONB支持索引;建议生产中使用JSONB。
  • 注意双引号和单引号的使用,在json中最外层使用单引号后,需要内部使用双引号。

1 适用于JSON/JSONB

操作符

实例

结果

->整数:选择数组中元素:输出json

select ‘[{“a”:“foo”},{“b”:“bar”},{“c”:“baz”}]’::json -> 2;

{“c”:“baz”}

->整数:选择数组中元素:输出json

select ‘[{“a”:“foo”},{“b”:“bar”},{“c”:“baz”}]’::json -> -3;

{“a”:“foo”}

->text:选择object中的元素:输出json

select ‘{“a”: {“b”:“foo”}}’::json -> ‘a’;

{“b”:“foo”}

->>整数:选择数组中元素:输出text

select ‘[1,2,3]’::json ->> 2;

3

->>text:选择object中的元素:输出text

select ‘{“a”:1,“b”:2}’::json ->> ‘b’;

2

#>路径:按路径选择元素:输出json

select ‘{“a”: {“b”: [“foo”,“bar”]}}’::json #> ‘{a,b,1}’;

“bar”

select ‘{“a”: {“b”: [“foo”,“bar”]}}’::json #> ‘{a,b}’;

[“foo”,“bar”]

select ‘{“a”: {“b”: [“foo”,“bar”]}}’::json #> ‘{a,c}’;

空:路径不通

#>>路径:按路径选择元素:输出text

select ‘{“a”: {“b”: [“foo”,“bar”]}}’::json #>> ‘{a,b,1}’;

bar

#>>多条路径只能返回最后匹配的一个)

2 适用于JSONB

子集、包含、组合

操作符

实例

结果

A@>B:B是A的子集?:输出bool

select ‘{“a”:1, “b”:2}’::jsonb @> ‘{“b”:2}’::jsonb;

t

select ‘{“a”:1, “b”:2}’::jsonb @> ‘{“b”:2, “a”:1}’::jsonb;

t

select ‘{“a”:1, “b”:2}’::jsonb @> ‘{“b”:2, “a”:2}’::jsonb;

f

select ‘{“a”:1, “b”:2}’::jsonb @> ‘{}’::jsonb;

t

select ‘{“a”:1, “b”:2}’::jsonb @> ‘[]’::jsonb;

f

select ‘{“a”:1, “b”:2}’::jsonb @> ‘null’::jsonb;

f

A<@B:A是B的子集?:输出bool

select ‘{“b”:2}’::jsonb <@ ‘{“a”:1, “b”:2}’::jsonb;

t

?text:顶级key或数组包含text?:输出bool

select ‘{“a”:1, “b”:2}’::jsonb ? ‘b’;

t

select ‘[“a”, “b”, “c”]’::jsonb ? ‘b’;

t

?|text[]:顶级key或数组包含text[]中的任意一个?:输出bool

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

t

?&text[]:顶级key或数组包含text[]中的全部?:输出bool

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

t

||:组合数组:输出jsonb

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

[“a”, “b”, “a”, “d”]

||:组合object(自动合并):输出jsonb

select '{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb;

{“a”: “b”, “c”: “d”}

select '{"a": "b"}'::jsonb || '{"a": "d"}'::jsonb;

{“a”: “d”}

||:组合数组与元素:输出jsonb

select '[1, 2]'::jsonb || '3'::jsonb;

[1, 2, 3]

||:组合object与元素:输出jsonb

select '{"a": "b"}'::jsonb || '42'::jsonb;

[{“a”: “b”}, 42]

||:组合object与数组:输出jsonb

select '{"a": "b"}'::jsonb || '[1, 2]'::jsonb;

[{“a”: “b”}, 1, 2]

删除

操作符

实例

结果

-text:删除key或数组元素:输出jsonb

select ‘{“a”: “b”, “c”: “d”}’::jsonb - ‘a’;

{“c”: “d”}

select ‘[“a”, “b”, “c”, “b”]’::jsonb - ‘b’;

[“a”, “c”]

-text[]:删除key或数组元素:输出jsonb

select ‘{“a”: “b”, “c”: “d”}’::jsonb - ‘{a,c}’::text[];

{}

select ‘[“a”, “b”, “c”]’::jsonb - 0;

[“b”, “c”]

select ‘[“a”, “b”, “c”]’::jsonb - 1;

[“a”, “c”]

select ‘[“a”, “b”, “c”]’::jsonb - -1;

[“a”, “b”]

select ‘[“a”, “b”, “c”]’::jsonb - -2;

[“a”, “c”]

select ‘[“a”, “b”, “c”]’::jsonb - -3;

[“b”, “c”]

总结:正数位置[0,1,2],负数位置[-3,-2,-1]

#-text[]:按路径删除:输出jsonb

select ‘[“a”, {“b”:1}]’::jsonb #- ‘{1,b}’;

[“a”, {}]

涉及jsonpath的操作符:@? jsonpath@@ jsonpath,请先阅读下面一章:JSONPATH

操作符

实例

结果

@? jsonpath:给出的jsonpath是否能找到元素

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

t

@? jsonpath:给出的jsonpath找到结果集,能否满足jsonpath中的布尔表达式?

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

t

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

f

JSONPATH

jsonpath是Postgresql12引入的特性,类似于使用XPATH的方式访问XML,参考了一些JS的语法引入的一种描述数据的语法。

例如下面一段json

代码语言:javascript复制
{
  "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
      }
    ]
  }
}

使用上面介绍的操作符#>> '{track,segments}'可以拿到segments数组值。

$.track.segments

代码语言:javascript复制
select '{
  "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
      }
    ]
  }
}'::jsonb #>> '{track,segments}';

-- 结果
[
  {"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, 
  {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}
]

也可以使用Jsonpath语言拿到segments数组:

代码语言:javascript复制
select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments');

-- 结果
[
  {"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, 
  {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}
]

再看两个例子:

$.track.segments[*].location

代码语言:javascript复制
select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments[*].location');

-- 结果
[47.763, 13.4034]
[47.706, 13.2635]


// `$.track.segments[0].location`

select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments[0].location');

-- 结果
[47.763, 13.4034]

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

@代指.最后的元素

代码语言:javascript复制
select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments[*].HR ? (@ > 130)');

-- 结果
135

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

这里@代指segments数组

代码语言:javascript复制
select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments[*] ? (@.HR > 130)."start time"');

-- 结果
"2018-10-14 10:39:21"

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

代码语言:javascript复制
select jsonb_path_query('{
  "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
      }
    ]
  }
}'::jsonb,
'$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"');

-- 结果
"2018-10-14 10:39:21"

0 人点赞