我有一个表,其中有一个名为“data”的列,类型为JSONB。我正在尝试根据最近的模型更改创建迁移脚本。 (postgres 9.4)
“gstNotRegisteredReason”, “gstRegistered”, “isIndiaGSTComposition” 在旧模型中需要在新模型中更改为“vatExemptionReason”,“vatExemption”,“auxiliaryProperties”。
旧模型:
{
"requestId":531956,
"requestVersion":5,
"supplier":{
"taxClassificationId":null,
"supplierScid":null,
"gstNotRegisteredReason":null, (boolean)
"gstRegistered":null, (boolean)
"isIndiaGSTComposition":true (boolean)
},
"createTime":"2017-07-17T06:48:52",
}
新模式:
{
"requestId":531956,
"requestVersion":5,
"supplier":{
"taxClassificationId":null,
"supplierScid":null,
"vatExemptionReason":null, (boolean)
"vatExemption":null, (boolean)
"AuxiliaryProperties":[
{
"id":"indiaGSTComposition",
"booleanValue":true
}
]
},
"createTime":"2017-07-17T06:48:52",
}
我想出了这个查询
update requests set data=regexp_replace(data::text, '"gstRegistered": ', '"vatExemption":', 'g')::jsonb;
update requests set data=regexp_replace(data::text, '"gstNotRegisteredReason": ', '"vatExemptionReason":', 'g')::jsonb;
但我不知道如何将isIndiaGSTComposition(boolean)转换为auxiliaryProperties(Array)。
请注意,如果isIndiaGSTComposition为null,则应为auxiliaryProperties:null。但如果它有真或假,则需要采用上述数据结构格式(如上面的“新模型”示例)。
感谢任何帮助。提前致谢 !
答案 0 :(得分:0)
Postgres 9.4 :
在该版本中,您也可以使用regexp_replace
函数:
UPDATE
requests
SET data =
regexp_replace(
data::text,
'"india"[\s]*:[\s]*(true|false|null)', -- A
'"aux":' || CASE
WHEN (data -> 'india')::text = 'null' THEN 'null' -- B
ELSE '[{"id":"india", "booleanValue":' || (data -> 'india')::text || '}]' -- C
END,
'g'
)::jsonb;
A:查找整个india
键/值对。使用[\s]*
,可以在空白格式不同的情况下使用空格。
B / C:替换为字符串'"aux":something'
。 “某物”是由CASE
子句构建的:如果india
具有字符串'null'
,则给出'null'
(B)。否则,以原始数组india
值(C)作为json数组字符串。
(我想知道为什么您需要一个aux
值的数组...)
Postgres 9.6 +
此版本具有更好的json支持,因此无需文本强制转换和regexp子句即可解决问题-以更类似于json的方式进行发言。
https://www.postgresql.org/docs/9.6/static/functions-json.html
UPDATE
requests
SET
data = jsonb_insert( -- A
data - 'india', -- B
'{aux}', -- C
CASE -- D
WHEN data -> 'india' = 'null' THEN 'null'
ELSE jsonb_insert( -- E
'[{"id":"india"}]'::jsonb, -- F
'{0, booleanValue}', -- G
data -> 'india' -- H
)
END
);
A:jsonb_insert
将新元素插入给定的json元素:
B:该函数的第一个参数是用于放置新对象的json。在这里,我使用数据对象,但之前删除了india
元素。
C:第二个参数-插入新元素的路径:新的json对象将作为键"aux"
的值插入。如果不存在(如本例所示),则会创建它。
D:第三个参数-要插入的元素:创建一个新元素。 CASE
子句逻辑与上述版本相似。如果india
的值为'null'
,请输入'null'
。否则:
E:创建一个新的json元素并插入旧的india
值
F:新元素是静态json数组'[{"id":"india"}]'
。
G:这是一条路径:取第一个元素("0"
),然后将新对象插入"booleanValue"
。如果此密钥不存在,请创建它。
H:采用旧的india
值。结果元素可以是[{"id":"india", "booelanValue: true"}]
。这是(C)中"aux"
元素的值