您最好的选择是将 MongoDB 的 ObjectId 字段迁移到 PostgreSQL 的 uuid 列。请注意,UUID 中有更多字节,因此您需要填充这些值。
查看更多信息:
如果你真的想使用bigints,你有两种选择:
1.创造全新的价值
- 创建您的架构(使用表、约束等)
- 在此架构中,使用
text / varchar 作为您的 ObjectId 值(暂时)
- 为所有关系创建foreign keys,为所有
ObjectId 列创建ON UPDATE CASCADE。
- 为所有具有
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 开头(或其他一些,修正起始值)
- 在每次迭代中,使用 N 个来自输入的最低有效位
- 计算结果为
<the_previous_result> # <value_from_2.>
- 继续 2. 当有更多未使用的位时(输入应该是旧输入,但 N 最低有效位)
这是一个 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 参数实际上是十六进制格式,并且 p_bits 参数永远不会大于 64。
但是如果你只是按原样使用它,你以后可能会在INSERT 上出现冲突的值。你可以做的是 f.ex。使用:
select -hex_xor('56c4100560b2d8308f4bde21', 63)
迁移时。这种方式迁移的ObjectIds 将始终为负值,而稍后生成的主键(例如,来自序列)将始终为正值。
http://rextester.com/RCVFN77368