• Postgresql JSON对象和数组查询


    一. Postgresql 9.5以下版本

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

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

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

    在这里插入图片描述

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

    在这里插入图片描述
    如果字段是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.1.4 在列表
    SELECT  * FROM "public"."tf_low_data_testUser" WHERE  "address" #>> '{0,name}' IN ('bbb','ccc')
    
    • 1

    在这里插入图片描述

    1.1.5 包含
    SELECT  * FROM "public"."tf_low_data_testUser" WHERE "address" #> '{0,roles,0,roleUsers}' @> '["eee"]'
    
    • 1
    • #>:获取在指定路径的 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
    • 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
    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%'
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当该层级类型是数组就添加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
    • 4
    • 5
    • 6

    查的是另外三条数据源
    在这里插入图片描述

    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
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果是数字类型后面需要转换 ::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
    • 3
    • 4
    • 5
    • 6

    查的是另外三条数据源
    在这里插入图片描述

    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
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    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
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    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"]'
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此时使用的操作符是->,返回值是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$")')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    同样支持NOT

    2.2 等值匹配

    SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].nickname ?(@ == "fff")')
    
    • 1

    在这里插入图片描述

    同样支持NOT

    2.3 时间搜索

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

    在这里插入图片描述

    同样支持NOT

    2.4 在列表

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

    在这里插入图片描述

    同样支持NOT

    2.5 包含

    等值匹配一样

    SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].address ?(@ == "222")')
    
    • 1

    在这里插入图片描述

    同样支持NOT

  • 相关阅读:
    药品专利如何申请?新药的专利保护期多久?
    仅需30行代码,轻松集成HMS Core视频编辑服务屏幕录制能力
    罗克韦尔AB PLC RSLogix数字量IO模块基本介绍
    越细粒度的锁越好吗?产生死锁怎么办?
    Kotlin内置函数:let,apply,run函数学习
    一、vmware和centos7.6安装
    一起来庆祝属于GISer的节日GIS DAY!
    还不懂JVM的设计原理与实现?这份《jvm虚拟机pdf》给你整的明明白白的
    前置放大器和功率放大器有什么区别?
    Linux shell的展开模式【实操演示】
  • 原文地址:https://blog.csdn.net/qq_38983728/article/details/132562441