Postgresql JSON对象和数组查询

文章目录

  • [一. Postgresql 9.5以下版本](#一. Postgresql 9.5以下版本)
      • [1.1 简单查询(缺陷:数组必须指定下标,不推荐)](#1.1 简单查询(缺陷:数组必须指定下标,不推荐))
          • [1.1.1 模糊查询](#1.1.1 模糊查询)
          • [1.1.2 等值匹配](#1.1.2 等值匹配)
          • [1.1.3 时间搜索](#1.1.3 时间搜索)
          • [1.1.4 在列表](#1.1.4 在列表)
          • [1.1.5 包含](#1.1.5 包含)
      • [1.2 多层级JSONArray(推荐)](#1.2 多层级JSONArray(推荐))
          • [1.2.1 模糊查询](#1.2.1 模糊查询)
          • [1.2.2 模糊查询 NOT](#1.2.2 模糊查询 NOT)
          • [1.2.3 等值匹配](#1.2.3 等值匹配)
          • [1.2.4 等值匹配 NOT](#1.2.4 等值匹配 NOT)
          • [1.2.5 时间搜索](#1.2.5 时间搜索)
          • [1.2.6 时间搜索 NOT](#1.2.6 时间搜索 NOT)
          • [1.2.7 在列表](#1.2.7 在列表)
          • [1.2.8 在列表 NOT](#1.2.8 在列表 NOT)
          • [1.2.9 包含](#1.2.9 包含)
          • [1.2.10 包含 NOT](#1.2.10 包含 NOT)
  • [二. Postgresql 9.5和以上版本](#二. Postgresql 9.5和以上版本)
      • [2.1 模糊查询](#2.1 模糊查询)
      • [2.2 等值匹配](#2.2 等值匹配)
      • [2.3 时间搜索](#2.3 时间搜索)
      • [2.4 在列表](#2.4 在列表)
      • [2.5 包含](#2.5 包含)

一. Postgresql 9.5以下版本

1.1 简单查询(缺陷:数组必须指定下标,不推荐)

1.1.1 模糊查询
复制代码
SELECT  * FROM "public"."tf_low_data_testUser" WHERE  "address" #>> '{0,name}' like '%bb%'

address字段是JSONArray类型,所以在路径中,使用数字索引来访问数组元素,从 0 开始计数。

1.1.2 等值匹配
复制代码
SELECT  * FROM "public"."tf_low_data_testUser" WHERE "address" #>> '{0,name}' = 'bbb'

如果字段是int类型,后面需要添加::int

1.1.3 时间搜索
复制代码
SELECT  * FROM "public"."tf_low_data_testUser" WHERE  "address" #>> '{0,date}' BETWEEN '2023-08-13' AND '2023-08-17'
1.1.4 在列表
复制代码
SELECT  * FROM "public"."tf_low_data_testUser" WHERE  "address" #>> '{0,name}' IN ('bbb','ccc')
1.1.5 包含
复制代码
SELECT  * FROM "public"."tf_low_data_testUser" WHERE "address" #> '{0,roles,0,roleUsers}' @> '["eee"]'
  • #>:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是json(b)
  • #>>:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是text

1.2 多层级JSONArray(推荐)

如果表中有一个字段posts,数据结构为

复制代码
[{
	"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结构

复制代码
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
复制代码
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 等值匹配
复制代码
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
复制代码
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 时间搜索
复制代码
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 在列表
复制代码
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 包含
复制代码
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路径,如果是数组添加[*])的正则查询达到模糊查询的效果

复制代码
-- 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 等值匹配

复制代码
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].nickname ?(@ == "fff")')

同样支持NOT

2.3 时间搜索

复制代码
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].date ?(@ >= "2022-01-02" && @ <= "2023-08-02")')

同样支持NOT

2.4 在列表

复制代码
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].nickname ?(@ == "ggg" || @ == "fff")')

同样支持NOT

2.5 包含

等值匹配一样

复制代码
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].address ?(@ == "222")')

同样支持NOT

相关推荐
Amctwd6 小时前
【PostgreSQL】不开启归档模式,是否会影响主从库备份?
数据库·postgresql
IvorySQL9 小时前
探索表访问方法功能:顺序扫描分析
数据库·postgresql·开源数据库
Kookoos1 天前
基于 PostgreSQL 的 ABP vNext + ShardingCore 分库分表实战
数据库·docker·postgresql·c#·.net
南棱笑笑生1 天前
20250510解决NanoPi NEO core开发板在Ubuntu core22.04.3系统下适配移远的4G模块EC200A-CN的问题
数据库·postgresql
kngines3 天前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】电商数据分析案例-9.3 商品销售预测模型
postgresql·数据分析·模型评估·arima·时间序列模型·prophet·mape
数巨小码人3 天前
PostgreSQL冻结过程
数据库·postgresql
Estrella-q3 天前
解决 Ubuntu DNS 无法解析问题(适用于虚拟机 & 长期使用)
数据库·ubuntu·postgresql
kngines3 天前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】电商数据分析案例-9.4 可视化报告输出
postgresql·数据分析·ipywidgets·pg_cron·gmv·商品交易总额
kngines4 天前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】8.4 数据故事化呈现(报告结构设计/业务价值提炼)
postgresql·数据分析·趋势预测模型·移动平均·cpa·生存分析模型·归因模型
文牧之4 天前
PostgreSQL 的 pg_current_logfile 函数
运维·数据库·postgresql