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

Mongodb Mongo到Postgres迁移-将Mongo hexa Id字段转换为更短的整数,mongodb,postgresql,int,migration,bigint,Mongodb,Postgresql,Int,Migration,Bigint,我正在将MongoDB迁移到postgres 多亏了postgres JSON,这使得将嵌套文档作为JSON移动变得很容易。但问题开始于迁移“ID”字段 Mongo生成一个大的十六进制数56c4100560b2d8308f4bde21 我尝试将其转换为BigInt,但不幸的是,它超出了范围26397231623443762880753094891 无法重新生成ID,因为它已在各地的文档之间链接 字符串不能用作ID字段,因为我正在移动到Postgres+JPA,我将使用自动生成序列向前移动 有没有

我正在将MongoDB迁移到postgres

多亏了postgres JSON,这使得将嵌套文档作为JSON移动变得很容易。但问题开始于迁移“ID”字段

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

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

  • 无法重新生成ID,因为它已在各地的文档之间链接

  • 字符串不能用作ID字段,因为我正在移动到Postgres+JPA,我将使用自动生成序列向前移动

  • 有没有办法,我可以把这个十六进制缩短为Int或BigInt的较短版本,同时,我应该保持uuique


    我尝试使用模数,但它带来了重复

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

    更多信息请参见:

    如果确实要使用
    bigint
    s,有两个选项:

    1。创建全新的价值观

  • 创建模式(使用表、约束等)
    • 在此模式中,使用
      text
      /
      varchar
      作为
      ObjectId
      值(目前)
  • 为您的所有关系创建,使用更新级联中的
    为所有
    ObjectId
    列创建
  • 为所有具有
    ObjectId
    列的表创建
  • 使用以下内容更新
    ObjectId
    列(当它们仍然是
    text
    /
    varchar
    ):

    (这将把更改传播到引用表,因为外键是在前面设置的。)

  • 删除外键
  • 将这些
    ObjectId
    列的列类型更改为
    bigint
  • 将序列更改为表列的
    所有
  • 更改表格以使用
    nextval('table\u name\u object\u id\u col\u seq')
    作为默认值
  • 重新添加外键
  • 此方法保证在迁移期间不会导致重复值。该序列可用于为主键创建新值

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

    截断将导致信息丢失,因此无论尝试何种方法,最终都可能会出现重复的值。但是,您可以通过使用f.ex来减少发生这种情况的机会。按位
    XOR
    (通常是PostgreSQL中的
    #
    运算符)而不是模数

    使用此函数f.ex。您可以将原始值用作:

  • 0
    开始(或使用其他固定起始值)
  • 在每次迭代中,使用输入的最低有效位数
  • 计算结果为
    #
  • 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$;
    
    移民时。这样,迁移的
    ObjectId
    s将始终为负值&随后生成的主键(例如,从序列中生成的主键)将始终为正值


    您可以使用与bytea相同的十六进制,我想应该是int/bigint。不幸的是,我无法更改它,此时您可能需要一些映射。像创建一个bigint序列用作ID和迁移数据save map old_hex->new_int somewhere通常,当您想将原始值用作
    bigint
    f.ex时,这些字段被迁移为a(这在JPA实现中通常得到很好的支持:例如,您可以通过多种方式生成随机UUID)。(并希望使用自动递增值)存在一个问题:如果现有行中出现一个较小的值,则解决方案将在到达该值时开始拒绝某些
    INSERT
    。请参阅f.ex。和
    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$;
    
    select -hex_xor('56c4100560b2d8308f4bde21', 63)