我最近一直在学习如何将MongoDB与Node.js一起使用,并且一直在想我将如何与团队的其他成员共享MongoDB更改,例如,通过git存储库。
如果我需要,例如MongoDB中名为users
的集合,并且该集合包含一些包含字段givenName
和familyName
的文档,那么这很容易做到当团队中的每个开发人员运行应用程序时,MongoDB将自动创建集合以及在代码中编写的字段。
现在我们可以说,出于某种原因,我需要将这两个字段重命名为forename
和surname
。
应用程序已经运行了一段时间,因此团队中的所有开发人员都拥有users
集合的本地副本,其中包含givenName
和familyName
的文档;生产服务器也是如此。
根据我的理解,我不能简单地更改代码中的字段名称以使用新的字段名称,因为我们将“丢失”旧字段名称中使用的任何数据(通过'丢失'我的当然意味着我们不会再看到旧数据,即使它仍然存在,正如预期的那样。)
所以我想我还必须在MongoDB shell中运行一个命令来重命名所有相关文档中的字段。
但是,如果我这样做,那么users
集合的本地副本只是最新的。
当使用MySQL时,我们只是在我们将在需要时运行的SQL文件中通过git共享我们的所有更改,或者如果它可用,则使用迁移,例如在PHP的Laravel框架中。
我们是否会像使用MySQL一样做,并保留我们在MongoDB shell中运行的changes.js
文件?
或者是否有更好的方法可以在应用程序代码本身中执行此操作,以便在开发人员运行应用程序时自动运行更改?
换句话说,在团队成员之间共享MongoDB变更的最佳做法是什么?
答案 0 :(得分:1)
数据迁移对于几乎所有持久性系统来说都是一个巨大的痛苦。有两个重要的策略:懒惰和渴望迁移。
对于 lazy 迁移,您需要使用代码才能处理旧数据结构和新数据结构。不幸的是,我不知道node.js mongodb驱动程序是如何在内部工作的。例如,在C#驱动程序中,可以注册自定义序列化程序,定义别名或使用C#的getter和setter来启用此行为。因此,Forename
字段将从givenName
或 Forename
中读取,但在将其存储回数据库时,它将始终序列化为Forename
此策略的问题在于它不适用于查询,例如{"Forename" : "John"}
会失败,因为某些文档尚未迁移。当然,索引甚至是独特的约束使事情变得更糟。
急切迁移需要某种基本上贯穿数据库中所有文档的脚本,并根据您的需要进行更新。通常,这是更简单的路径,它不会破坏查询。但是,您需要在正确的时间运行此脚本,对于大型数据集,这可能需要一段时间。在此期间,您的系统已关闭或提供不正确的结果。
因此,数据量越大,必须允许的“懒惰”越多。例如,您可能希望按用户运行脚本(而不是按自然顺序),这样用户就不太可能达到其数据的“半迁移”状态。不过,您希望您的代码能够处理此问题。
对于这两种策略,当事情变得复杂时,可能需要进行模式版本控制,即单个文档具有_sv
之类的字段,并且有些脚本知道如何从版本n
获取到版本{{ 1}}。然后,您可以使脚本非常抽象和幂等,这样您就可以运行它们,而不必担心在新数据上运行旧脚本会破坏任何内容。