Mongo 到 Postgres 迁移 - 将 mongo hexa Id 字段转换为更短的整数

Mongo to Postgres migration - Convert mongo hexa Id field to shorter integer

正在将 MongoDB 迁移到 postgres。

感谢 postgres JSON ,这使得移动嵌套文档变得容易 JSON。但问题始于迁移 "ID" 字段。

Mongo生成一个大的十六进制数56c4100560b2d8308f4bde21

我尝试将其转换为 BigInt,不幸的是它超出了范围 26397231623443762880753094891

  1. 无法重新生成ID,因为它在各处的文档之间相互链接。

  2. 字符串不能用作 ID 字段,因为我正在迁移到 Postgres + JPA,并且我将继续使用自动生成序列。

有什么办法,我可以将这个十六进制缩短为更短版本的 Int 或 BigInt ,同时我应该保持唯一性

我尝试取模,但它会带来重复

您最好的选择是将 MongoDB 的 ObjectId 字段迁移到 PostgreSQL 的 uuid 列。请注意,UUID 中有更多字节,因此您需要填充这些值。

查看更多信息:

如果你真的想使用bigints,你有两个选择:

1.创造全新的价值

  1. 创建您的架构(使用 tables、约束等)
    • 在此架构中,使用 text / varchar 作为您的 ObjectId 值(目前)
  2. 为所有关系创建 foreign keys,为所有 ObjectId 列创建 ON UPDATE CASCADE
  3. 为具有 ObjectId 列的所有 table 创建 sequences
  4. 更新 ObjectId 列(虽然它们仍然是 text / varchar),其中:

    UPDATE table_name
    SET    object_id_col = nextval('table_name_object_id_col_seq')::text
    

    (这会将更改传播到引用 tables,因为外键已较早设置。)

  5. 删除外键
  6. 将这些 ObjectId 列的列类型更改为 bigint
  7. 将您的序列更改为 OWNED BY table 列
  8. 更改 tables 以使用 nextval('table_name_object_id_col_seq') 作为默认值
  9. 重新添加外键

此方法保证在迁移过程中不会出现重复值。并且该序列可用于为主键创建新值。

2。以某种方式使用您的原始值

截断会导致信息丢失,因此无论您尝试什么方法,您可能最终得到重复值。但是,您可以使用 f.ex 来减少这种情况的发生。按位 XOR(通常是 Postgre# 中的运算符SQL)而不是取模。

有了这个功能f.ex。您可以将原始值用作:

  1. 0 开始(或其他一些,固定起始值)
  2. 每次迭代,使用来自输入
  3. N个最低有效位
  4. 计算结果为<the_previous_result> # <value_from_2.>
  5. 继续 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 将始终为负值,之后生成的主键(f.ex。来自序列)将始终为正值。

http://rextester.com/RCVFN77368