将MongoDB迁移到postgres。
感谢postgres JSON,它可以轻松地将嵌套文档作为JSON移动。但问题始于迁移“ID”字段。
Mongo生成一个大的十六进制数56c4100560b2d8308f4bde21
我尝试将其转换为BigInt,但不幸的是,它超出了范围26397231623443762880753094891
无法重新生成ID,因为它在各地的文档之间相互关联。
字符串不能用作ID字段,因为我移动到Postgres + JPA,我将使用自动生成序列向前移动。
有什么办法,我可以将这个十六进制缩短为更短版本的Int或BigInt,同时,我应该保持优秀感
我尝试了模数,但它带来了重复
答案 0 :(得分:2)
您最好的选择是将MongoDB的ObjectId
字段迁移到PostgreSQL的uuid
列。请注意,UUID中包含更多字节,因此您需要填充值。
详情请见:
如果你真的想使用bigint
,你有两个选择:
<强> 1。创建全新的值
text
值使用varchar
/ ObjectId
(暂时)ON UPDATE CASCADE
列都ObjectId
。ObjectId
列的表格创建sequences。更新ObjectId
列(虽然它们仍为text
/ varchar
),但有:
UPDATE table_name
SET object_id_col = nextval('table_name_object_id_col_seq')::text
(这会将更改传播到引用表,因为之前已设置了外键。)
ObjectId
列的列类型更改为bigint
OWNED BY
表格列nextval('table_name_object_id_col_seq')
作为默认值保证此方法在迁移期间不会导致重复值。序列可用于为主键创建新值。
<强> 2。以某种方式使用原始值
截断会导致信息丢失,因此无论您采用何种方法,可能都会以重复值结束。但是,您可以通过使用f.ex来减少这种情况。按位XOR
(通常是PostgreSQL中的#
运算符)而不是模数。
使用此功能f.ex.您可以将原始值用作:
0
开头(或其他一些,修复起始值)<the_previous_result> # <value_from_2.>
这是一个SQL函数,它可以做到:
create or replace function hex_xor(p_hex text, p_bits int default 64, p_default bigint default 0)
returns bigint
language sql
immutable
as $func$
with recursive r as (
select ('x' || p_hex)::varbit h, p_default r, 0 i
union all
select case
when bit_length(h) <= p_bits then varbit ''
else substring(h for bit_length(h) - p_bits)
end,
r # case
when bit_length(h) <= p_bits then h::bit(64)::bigint
else substring(h from bit_length(h) - p_bits + 1 for p_bits)::bigint
end,
i + 1
from r
where bit_length(h) > 0
)
select r
from r
order by i desc
limit 1
$func$;
这假设p_hex
参数实际上是十六进制格式&amp; p_bits
参数永远不会超过64
。
但是如果你只是按原样使用它,你可能会在INSERT
之后使用相互冲突的值来结束。你能做的就是f.ex.使用:
select -hex_xor('56c4100560b2d8308f4bde21', 63)
迁移后。这种方式,迁移的ObjectId
将始终为负值&amp;后来生成的主键(序列中的f.ex.)将始终为正。