Postgresql JSON对象和数组查询功能实现
脚本之家 / 编程助手:解决程序员“几乎”所有问题!
脚本之家官方知识库 → 点击立即使用
一. Postgresql 9.5以下版本
1.1 简单查询(缺陷:数组必须指定下标,不推荐)
1.1.1 模糊查询
address字段是JSONArray类型,所以在路径中,使用数字索引来访问数组元素,从 0 开始计数。
1.1.2 等值匹配
如果字段是int
类型,后面需要添加::int
1.1.3 时间搜索
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE "address" #>> '{0,date}' BETWEEN '2023-08-13' AND '2023-08-17' |
1.1.4 在列表
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE "address" #>> '{0,name}' IN ( 'bbb' , 'ccc' ) |
1.1.5 包含
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE "address" #> '{0,roles,0,roleUsers}' @> '["eee"]' |
#>
:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是json(b)
#>>
:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是text
1.2 多层级JSONArray(推荐)
如果表中有一个字段posts
,数据结构为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | [{ "name" : "aaa" , "ports" : [{ "port" : 443 , "nickname" : "ggg" , "date" : "2023-08-29" , "address" : [ "111" , "222" ] }, { "port" : 80 , "nickname" : "fff" , "date" : "2022-08-29" , "address" : [ "333" , "444" ] }] }, { "name" : "bbb" , "ports" : [{ "port" : 2443 , "nickname" : "hhh" , "date" : "2021-08-29" , "address" : [ "999" ] }, { "port" : 280 , "nickname" : "jjj" , "date" : "2020-08-29" , "address" : [ "111111" ] }] }] |
1.2.1 模糊查询
查询nickname like '%jj%'
可以看出有两层JSONArray结构
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'nickname' ) like '%gg%' ); |
当该层级类型是数组就添加
CROSS JOIN jsonb_array_elements(obj1->'ports') as arr2(obj2)
1.2.2 模糊查询 NOT
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE NOT EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'nickname' ) like '%gg%' ); |
查的是另外三条数据源
1.2.3 等值匹配
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'port' ):: int = 80 ); |
如果是数字类型后面需要转换
::int
,因为->>
操作符的返回类型是text
1.2.4 等值匹配 NOT
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE NOT EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'port' ):: int = 80 ); |
查的是另外三条数据源
1.2.5 时间搜索
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'date' ) BETWEEN '2022-08-13' AND '2023-08-17' ); |
1.2.6 时间搜索 NOT
查的是另外三条数据源
1.2.7 在列表
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2->> 'nickname' ) IN ( 'ggg' , 'fff' ) ); |
1.2.8 在列表 NOT
查的是另外三条数据源
1.2.9 包含
1 2 3 4 5 6 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE EXISTS ( SELECT 1 FROM jsonb_array_elements( "ports" ) as arr1(obj1) CROSS JOIN jsonb_array_elements(obj1-> 'ports' ) as arr2(obj2) WHERE (obj2-> 'address' ) @> '["444"]' ); |
此时使用的操作符是
->
,返回值是jsonb
类型
1.2.10 包含 NOT
查的是另外三条数据源
二. Postgresql 9.5和以上版本
也兼容上面的JSON查询
2.1 模糊查询
使用函数
jsonb_path_exists
(可以指定JSON
路径,如果是数组添加[*]
)的正则查询达到模糊查询的效果
1 2 3 4 5 6 7 8 | -- like '%ggg%' SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ like_regex "g")' ) -- 左模糊 like '%g' SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ like_regex "g$")' ) -- 右模糊 like 'g%' SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ like_regex "^g")' ) -- 等值匹配 SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ like_regex "^ggg$")' ) |
同样支持
NOT
2.2 等值匹配
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ == "fff")' ) |
同样支持
NOT
2.3 时间搜索
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].date ?(@ >= "2022-01-02" && @ <= "2023-08-02")' ) |
同样支持
NOT
2.4 在列表
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].nickname ?(@ == "ggg" || @ == "fff")' ) |
同样支持
NOT
2.5 包含
和
等值匹配
一样
1 | SELECT * FROM "public" . "tf_low_data_testUser" WHERE jsonb_path_exists( "ports" , '$[*].ports[*].address ?(@ == "222")' ) |
同样支持
NOT
到此这篇关于Postgresql JSON对象和数组查询的文章就介绍到这了,更多相关Postgresql JSON对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
PostgreSQL索引扫描时为什么index only scan不返回ctid
这篇文章主要介绍了PostgreSQL索引扫描时为什么index only scan不返回ctid的原因探索,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-09-09postgresql 数据库 与TimescaleDB 时序库 join 在一起
这篇文章主要介绍了postgresql 数据库 与TimescaleDB 时序库 join 在一起,需要的朋友可以参考下2020-12-12postgresql 中的几个 timeout参数 用法说明
这篇文章主要介绍了postgresql中的几个timeout参数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2021-01-01
最新评论