在 postgresql 中编辑 jsonb 数组的字段
Edit fields of a jsonb array in postgresql
我在数据库中有以下 jsonb:
[
{
"state": 2,
"activity": "EJECUCIÓN",
"final_date": "2020-02-24",
"activity_id": 1,
"current_days": -7,
"initial_date": "2020-02-24",
},
{
"state": 2,
"activity": "REVISIÓN",
"final_date": "2020-02-25",
"activity_id": 2,
"current_days": 0,
"initial_date": "2020-02-25",
},
{
"state": 2,
"activity": "RECEPCIÓN",
"final_date": "2020-02-27",
"activity_id": 4,
"current_days": 0,
"initial_date": "2020-02-27"
} ]
我运行下面的查询来更新current_days字段:
WITH activity_state as ( SELECT taex_id,('{'||index-1||',current_days}')::text[] as pathe ,
((task_activity->>'final_date')::date - current_date) as current_days,
task_activity->'state' as state,
task_activity->>'final_date' as final_date,
task_activity->>'current_days' as curren FROM task_executions,jsonb_array_elements(taex_activitygraph) with ordinality arr(task_activity,index) WHERE task_activity->>'state' = '2' )
update task_executions SET taex_activitygraph = jsonb_set(taex_activitygraph,activity_state.pathe,to_jsonb(current_days),true) FROM activity_state WHERE task_executions.taex_id = activity_state.taex_id AND activity_state.state = '2'
但是该查询只更新 JSON 数组中存在的第一个元素,其他元素虽然在查询的第一部分中,但不会发生变化。
( SELECT taex_id,('{'||index-1||',current_days}')::text[] as pathe ,
((task_activity->>'final_date')::date - current_date) as current_days,
task_activity->'state' as state,
task_activity->>'final_date' as final_date,
task_activity->>'current_days' as curren FROM task_executions,jsonb_array_elements(taex_activitygraph) with ordinality arr(task_activity,index) WHERE task_activity->>'state' = '2' )
它给我带来了数组中所有应该更新的元素,但第二部分是应该更新它们的地方:
update task_executions SET taex_activitygraph = jsonb_set(taex_activitygraph,activity_state.pathe,to_jsonb(current_days),true) FROM activity_state WHERE task_executions.taex_id = activity_state.taex_id AND activity_state.state = '2'
给我更新第一个项目。
假设这个结构和数据:
postgres=# \d task_executions
Table "public.task_executions"
Column | Type | Collation | Nullable | Default
--------------------+-------+-----------+----------+---------
task_activitygraph | jsonb | | |
postgres=# SELECT jsonb_pretty(task_activitygraph) FROM task_executions ;
jsonb_pretty
--------------------------------------
[ +
{ +
"state": 2, +
"activity": "EJECUCIÓN", +
"final_date": "2020-02-24", +
"activity_id": 1, +
"current_days": -7, +
"initial_date": "2020-02-24"+
}, +
{ +
"state": 2, +
"activity": "REVISIÓN", +
"final_date": "2020-02-25", +
"activity_id": 2, +
"current_days": 0, +
"initial_date": "2020-02-25"+
} +
]
(1 row)
...此更新应该有效:
postgres=# UPDATE task_executions
SET task_activitygraph = (
SELECT jsonb_agg(
CASE WHEN elem->>'state' = '2'
THEN
jsonb_set(
elem,
'{current_days}',
to_jsonb((elem->>'final_date')::date - current_date)
)
ELSE
elem
END
)
FROM jsonb_array_elements(task_activitygraph) AS a(elem)
);
UPDATE 1
文档:https://www.postgresql.org/docs/9.5/functions-json.html
旁注:在事务数据库中(您有许多并发客户端,处理速度和存储效率很重要),如果您的对象具有固定结构,请勿将数据存储为 JSON。请改用关系数据模型。
我在数据库中有以下 jsonb:
[
{
"state": 2,
"activity": "EJECUCIÓN",
"final_date": "2020-02-24",
"activity_id": 1,
"current_days": -7,
"initial_date": "2020-02-24",
},
{
"state": 2,
"activity": "REVISIÓN",
"final_date": "2020-02-25",
"activity_id": 2,
"current_days": 0,
"initial_date": "2020-02-25",
},
{
"state": 2,
"activity": "RECEPCIÓN",
"final_date": "2020-02-27",
"activity_id": 4,
"current_days": 0,
"initial_date": "2020-02-27"
} ]
我运行下面的查询来更新current_days字段:
WITH activity_state as ( SELECT taex_id,('{'||index-1||',current_days}')::text[] as pathe ,
((task_activity->>'final_date')::date - current_date) as current_days,
task_activity->'state' as state,
task_activity->>'final_date' as final_date,
task_activity->>'current_days' as curren FROM task_executions,jsonb_array_elements(taex_activitygraph) with ordinality arr(task_activity,index) WHERE task_activity->>'state' = '2' )
update task_executions SET taex_activitygraph = jsonb_set(taex_activitygraph,activity_state.pathe,to_jsonb(current_days),true) FROM activity_state WHERE task_executions.taex_id = activity_state.taex_id AND activity_state.state = '2'
但是该查询只更新 JSON 数组中存在的第一个元素,其他元素虽然在查询的第一部分中,但不会发生变化。
( SELECT taex_id,('{'||index-1||',current_days}')::text[] as pathe ,
((task_activity->>'final_date')::date - current_date) as current_days,
task_activity->'state' as state,
task_activity->>'final_date' as final_date,
task_activity->>'current_days' as curren FROM task_executions,jsonb_array_elements(taex_activitygraph) with ordinality arr(task_activity,index) WHERE task_activity->>'state' = '2' )
它给我带来了数组中所有应该更新的元素,但第二部分是应该更新它们的地方:
update task_executions SET taex_activitygraph = jsonb_set(taex_activitygraph,activity_state.pathe,to_jsonb(current_days),true) FROM activity_state WHERE task_executions.taex_id = activity_state.taex_id AND activity_state.state = '2'
给我更新第一个项目。
假设这个结构和数据:
postgres=# \d task_executions
Table "public.task_executions"
Column | Type | Collation | Nullable | Default
--------------------+-------+-----------+----------+---------
task_activitygraph | jsonb | | |
postgres=# SELECT jsonb_pretty(task_activitygraph) FROM task_executions ;
jsonb_pretty
--------------------------------------
[ +
{ +
"state": 2, +
"activity": "EJECUCIÓN", +
"final_date": "2020-02-24", +
"activity_id": 1, +
"current_days": -7, +
"initial_date": "2020-02-24"+
}, +
{ +
"state": 2, +
"activity": "REVISIÓN", +
"final_date": "2020-02-25", +
"activity_id": 2, +
"current_days": 0, +
"initial_date": "2020-02-25"+
} +
]
(1 row)
...此更新应该有效:
postgres=# UPDATE task_executions
SET task_activitygraph = (
SELECT jsonb_agg(
CASE WHEN elem->>'state' = '2'
THEN
jsonb_set(
elem,
'{current_days}',
to_jsonb((elem->>'final_date')::date - current_date)
)
ELSE
elem
END
)
FROM jsonb_array_elements(task_activitygraph) AS a(elem)
);
UPDATE 1
文档:https://www.postgresql.org/docs/9.5/functions-json.html
旁注:在事务数据库中(您有许多并发客户端,处理速度和存储效率很重要),如果您的对象具有固定结构,请勿将数据存储为 JSON。请改用关系数据模型。