Mongo to Postgres migration - 将mongo hexa Id字段转换为较短的整数

时间:2017-03-27 06:51:54

标签: mongodb postgresql int migration bigint

将MongoDB迁移到postgres。

感谢postgres JSON,它可以轻松地将嵌套文档作为JSON移动。但问题始于迁移“ID”字段。

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

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

  1. 无法重新生成ID,因为它在各地的文档之间相互关联。

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

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

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

1 个答案:

答案 0 :(得分:2)

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

详情请见:

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

<强> 1。创建全新的值

  1. 创建您的架构(包含表格,约束等)
    • 在此架构中,对text值使用varchar / ObjectId(暂时)
  2. 为您的所有关系创建foreign keys,所有ON UPDATE CASCADE列都ObjectId
  3. 为所有包含ObjectId列的表格创建sequences
  4. 更新ObjectId列(虽然它们仍为text / varchar),但有:

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

    (这会将更改传播到引用表,因为之前已设置了外键。)

  5. 删除外键
  6. 将这些ObjectId列的列类型更改为bigint
  7. 将您的序列更改为OWNED BY表格列
  8. 将表更改为使用nextval('table_name_object_id_col_seq')作为默认值
  9. 重新添加外键
  10. 保证此方法在迁移期间不会导致重复值。序列可用于为主键创建新值。

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

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

    使用此功能f.ex.您可以将原始值用作:

    1. 0开头(或其他一些,修复起始值)
    2. 每次迭代时,使用输入
    3. N 个最低有效位
    4. 将结果计算为<the_previous_result> # <value_from_2.>
    5. 继续2.当有更多未使用的位(输入应该是旧输入但 N 最低有效位)
    6. 这是一个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.)将始终为正。

      http://rextester.com/RCVFN77368