SELECT * FROM "public"."tf_low_data_testUser" WHERE "address" #>> '{0,name}' like '%bb%'
address字段是JSONArray类型,所以在路径中,使用数字索引来访问数组元素,从 0 开始计数。
SELECT * FROM "public"."tf_low_data_testUser" WHERE "address" #>> '{0,name}' = 'bbb'
如果字段是int类型,后面需要添加::int
SELECT * FROM "public"."tf_low_data_testUser" WHERE "address" #>> '{0,date}' BETWEEN '2023-08-13' AND '2023-08-17'
SELECT * FROM "public"."tf_low_data_testUser" WHERE "address" #>> '{0,name}' IN ('bbb','ccc')
SELECT * FROM "public"."tf_low_data_testUser" WHERE "address" #> '{0,roles,0,roleUsers}' @> '["eee"]'
- #>:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是json(b)
- #>>:获取在指定路径的 JSON 对象,路径不存在则返回空。返回类型是text
如果表中有一个字段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"] }] }]
查询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)
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%' );
查的是另外三条数据源
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
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 );
查的是另外三条数据源
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' );
查的是另外三条数据源
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') );
查的是另外三条数据源
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类型
查的是另外三条数据源
也兼容上面的JSON查询
使用函数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
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].nickname ?(@ == "fff")')
同样支持NOT
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].date ?(@ >= "2022-01-02" && @ <= "2023-08-02")')
同样支持NOT
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].nickname ?(@ == "ggg" || @ == "fff")')
同样支持NOT
和等值匹配一样
SELECT * FROM "public"."tf_low_data_testUser" WHERE jsonb_path_exists("ports", '$[*].ports[*].address ?(@ == "222")')
同样支持NOT