1. 程式人生 > 實用技巧 >Postgresql 更新jsonb 欄位

Postgresql 更新jsonb 欄位

參考文件

https://www.cnblogs.com/zhangfx01/p/9506219.html

https://stackoverflow.com/questions/18209625/how-do-i-modify-fields-inside-the-new-postgresql-json-datatype/23500670#23500670

一、查詢jsonb欄位

select id,jsonb_v::jsonb->>'celldata' ,jsonb_v->>'celldata'  from t_user where id=35;

update t_user set jsonb_v=jsonb_v||'
{"address":"上海浦東"}'::jsonb where id=35; -- 新增address

update t_user set jsonb_v=jsonb_v||'{"address":"被凍結上海浦東"}'::jsonb where id=35;  -- 修改address的值

update t_user set jsonb_v=jsonb_v - 'address' where id=35; -- 刪除address 

2、複雜物件

{
    "myinfo": {
        "name": "xc",
        "myaddress"
: { "city": "上海", "pre": "" } } } {"myinfo":{"name":"xc","myaddress":{"city":"上海","pre":""}}}

-- 新增到根節點下

update t_user set jsonb_v=jsonb_v||'{"myinfo":{"name":"xc","myaddress":{"city":"上海","pre":"區"}}}'::jsonb where id=35;

-- 增加一個內嵌age欄位 {"myinfo":{"myaddress":{"age":12}}}

{
    "myinfo": {
        "myaddress": {
            "age": 12
        }
    }
}
-- 錯誤! 以下方法把整個myinfo欄位都作為修改

update t_user set jsonb_v=jsonb_v||'{"myinfo":{"myaddress":{"age":12}}}'::jsonb where id=35;  

-- 對myinfo->myaddress 增加一個age鍵 (其中true的作用為,沒有就新增一個鍵)

update t_user set jsonb_v= jsonb_set(jsonb_v,'{myinfo,myaddress,age}'::text[],'"124"',true) where id=35;

update t_user set jsonb_v= jsonb_set(jsonb_v,'{myinfo,myaddress,age}'::text[],'12',true) where id=35;

3、List

-- 增加一個集合

update t_user set jsonb_v=jsonb_v||'{"celldata":[]}'::jsonb where id=35;

-- 陣列中插入一條記錄

update t_user set jsonb_v=jsonb_insert(jsonb_v::jsonb,'{celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false) where id =35;

-- 刪除集合

update t_user set jsonb_v=jsonb_v - 'celldata' where id=35;

-- celldata集合中第二個的v值整體改變

update t_user set jsonb_v= jsonb_set(jsonb_v,'{celldata,1,v}'::text[],'{"con":"new str"}',true) where id=35;

-- celldata集合中第二個v的某個key的值改變

update t_user set jsonb_v= jsonb_set(jsonb_v,'{celldata,1,v,con1}'::text[],'"new str"',true) where id=35;

-- 刪除celldata集合中的第二個

update t_user set jsonb_v = jsonb_v #- '{celldata,1}' where id=35;

-- 集合在其他層級新增

update t_user set jsonb_v=jsonb_v||'{"myinfo":{"celldata":[]}}'::jsonb where id=35;

-- 集合在其他層級 新增元素

update t_user set jsonb_v=jsonb_insert(jsonb_v,'{myinfo,celldata,0}','{"c":1,"r":1,"v":{"con":"str"}}',false) where id =35;

-- 集合在其他層級 新增元素到集合尾部

update t_user set jsonb_v=jsonb_insert(jsonb_v,'{myinfo,celldata,-1}','{"c":21,"r":21,"v":{"con":"str"}}',true) where id =35;

-- 集合在其他層級 元素修改

update t_user set jsonb_v= jsonb_set(jsonb_v,'{myinfo,celldata,0,v,con}'::text[],'"new str"',true) where id=35;

-- 查詢時 返回修改過資料

select
    jsonb_agg(
        case when c1 @> '{"c":21,"r":21}'
        then '{"c":21,"r":21,"v":"vasfaf"}'
        else c1 end)
from
    (
        select jsonb_array_elements(jsonb_v->'myinfo'->'celldata') c1 
        from t_user where id=35
    ) as t;

4、建立索引

Create index 索引名 on 表名(欄位名)
-- jsonb欄位建立索引
create index idx_ay_json_v on ay_json_test using gin(json_value jsonb_path_ops );

5、建立自增ID

CREATE SEQUENCE gys.mytable_myid_seq
CYCLE
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 99999999
    CACHE 1;

ALTER SEQUENCE gys.mytable_myid_seq
OWNER TO postgres;

sql使用時

String sql = "insert into t_user (id,username,password,age,remark,updatetime,jsonb) values " +
        " (nextval('ay_json_test_id_seq'),?,?,?,?,now(),?)";

6、jsonb欄位中的key進行排序查詢

select * from ay_json_test order by json_value::json->>'agent' desc
order by jsonb欄位名::json->>key desc/asc

7、jsonb欄位中的key進行篩選

select * from ay_json_test where json_value @>'{"agent":"02"}'::jsonb;
Where jsonb欄位名 @>’json串’::jsonb

8、jsonb欄位返回的結果只獲取其中幾個key

-- 從普通欄位以及jsonb欄位中獲取指定的幾個key返回結果

select id,json_value::json->>'agent' as agent,json_value::json->>'ay_name' as ay_name from ay_json_test t ;

-- 從普通欄位以及jsonb欄位中獲取指定的幾個key返回json結果

select row_to_json(a.*) from (

select json_value::json->>'agent' as agent ,json_value::json->>'ay_name' as ay_name from ay_json_test t

) a;

9、按頁返回資料 2個方法效率未知

-- ay_name 排序 獲取第4條記錄開始的記錄

-- 方法一

SELECT a.* FROM
( SELECT t.*, ROW_NUMBER() over(ORDER BY json_value :: json ->> 'an_name' ) AS rn FROM ay_json_test t ) a
WHERE rn > 3 and rn<6

-- 方法二

select * from ay_json_test order by json_value::json->>'ay_name'  limit 2 offset 3

10、獲取陣列元素數量

select jsonb_array_length(jsonb_v->'myinfo'->'celldata')  from t_user where id=35 ;
-- 或者
select jsonb_array_length(c1) from  (
    select jsonb_v->'myinfo'->'celldata' as c1 from t_user where id=35 
) as t;

11、獲取jsonb欄位長度

select jsonb_v as v,
CHAR_LENGTH(jsonb_v :: text) as l,
LENGTH(jsonb_v :: text) as l2,
CHARACTER_LENGTH(jsonb_v :: text) as l3,
octet_length(jsonb_v :: text) as l4
from t_user;

12、複雜處理

C=1 r=2 修改v
Insert into t_user(id,jsonb_v) values(113,’[{"c":2,"r":2,"v":{"con":"str"}},{"c":1,"r":1,"v":{"con":"new str"}},{"c":21,"r":21,"v":{"con":"str"}},{"c":20,"r":21,"v":{"con":"str"}}]’);

先分拆資料,得到最終結果

select jsonb_agg(col2) from 
(
  select row_to_json(t2) col2 from
  (
    select c, r , 
      case when c=20 and r=21  then '{"k":1,"y":"2"}'
      else v end v
    from 
          (select jsonb_v  from t_user where id=113) as t1,
          jsonb_to_recordset ( t1.jsonb_v ) x ( C INT, r INT, v jsonb )
  ) t2
) t3

c>=20 c=c+20

select jsonb_agg(col2) from 
(
  select row_to_json(t2) col2 from
  (
    select c,
      case when r>= 20 then r+20
      else r end r,
      v
    from 
          (select jsonb_v  from t_user where id=113) as t1,
          jsonb_to_recordset ( t1.jsonb_v ) x ( C INT, r INT, v jsonb )
  ) t2
) t3