正文
在处理了 MongoDB 中独有的嵌入式关系之后,我们就需要解决一些复杂的集合类型了,比如数组和哈希,如果我们使用 MySQL5.7 或者 PostgreSQL 的话,其实并不需要对他们进行处理,因为最新版本的 MySQL 和 PostgreSQL 已经提供了对 JSON 的支持,不过作者还是将项目中的数组和哈希都变成了常见的数据结构。
在这个可选的过程中,其实并没有什么标准答案,我们可以根据需要将不同的数据转换成不同的数据结构:
比如,将数组变成字符串或者一对多关系,将哈希变成当前文档的键值对等等,如何处理这些集合数据其实都要看我们的业务逻辑,在改变这些字段的同时尽量为上层提供一个与原来直接
.tags
或者
.categories
结果相同的 API:
这一步其实也是可选的,上述代码只是为了减少其他地方的修改负担,当然如果你想使用 MySQL5.7 或者 PostgreSQL 数据库对 JSON 的支持也没有什么太大的问题,只是在查询集合字段时有一些不方便。
Mongoid 的『小兄弟』们
在使用 Mongoid 进行开发期间难免会用到一些相关插件,比如
mongoid-enum
、
mongoid-slug
和
mongoid-history
等,这些插件的实现与 ActiveRecord 中具有相同功能的插件在实现上有很大的不同。
对于有些插件,比如 mongoid-slug 只是在引入插件的模型的文档中插入了
_slugs
字段,我们只需要在进行数据迁移忽略这些添加的字段并将所有的
#slug
方法改成
#id
,不需要在预处理的过程中做其它的改变。而枚举的实现在 Mongoid 的插件和 ActiveRecord 中就截然不同了:
mongoid-enum 使用字符串和
_status
来保存枚举类型的字段,而 ActiveRecord 使用整数和
status
表示枚举类型,两者在底层数据结构的存储上有一些不同,我们会在之后的迁移脚本中解决这个问题。
如果在项目中使用了很多 Mongoid 的插件,由于其实现不同,我们也只能根据不同的插件的具体实现来决定如何对其进行迁移,如果使用了一些支持特殊功能的插件可能很难在 ActiveRecord 中找到对应的支持,在迁移时可以考虑暂时将部分不重要的功能移除。
主键与 UUID
我们希望从 MongoDB 迁移到 MySQL 的另一个重要原因就是 MongoDB 每一个文档的主键实在是太过冗长,一个 32 字节的
_id
无法给我们提供特别多的信息,只能增加我们的阅读障碍,再加上项目中并没有部署 MongoDB 集群,所以没能享受到用默认的 UUID 生成机制带来的好处。
我们不仅没有享受到 UUID 带来的优点,它还在迁移 MySQL 的过程中为我们带来了很大的麻烦,一方面是因为 ActiveRecord 的默认主键是整数,不支持 32 字节长度的 UUID,如果我们想要不改变 MongoDB 的 UUID,直接迁移到 MySQL 中使用其实也没有什么问题,只是我们要将默认的整数类型的主键变成字符串类型,同时要使用一个 UUID 生成器来保证所有的主键都是根据时间递增的并且不会冲突。
如果准备使用 UUID 加生成器的方式,其实会省去很多迁移的时间,不过看起来确实不是特别的优雅,如何选择还是要权衡和评估,但是如果我们选择了使用
integer
类型的自增主键时,就需要做很多额外的工作了,首先是为所有的表添加
uuid
字段,同时为所有的外键例如
post_id
创建对应的
post_uuid
字段,通过
uuid
将两者关联起来:
在数据的迁移过程中,我们会将原有的
_id
映射到
uuid
中,
post_id
映射到
post_uuid
上,我们通过保持
uuid
和
post_uuid
之间的关系保证模型之间的关系没有丢失,在迁移数据的过程中
id
和
post_id
是完全不存在任何联系的。
当我们按照
_id