Sequelize 迁移中的关联

Posted

技术标签:

【中文标题】Sequelize 迁移中的关联【英文标题】:Associations in Sequelize migrations 【发布时间】:2016-01-27 10:29:00 【问题描述】:

我的应用目前使用 Sequelize sync() 方法创建数据库,我想将其更改为使用迁移系统。

我的一个模型与其他模型有belongsTo() 关联,我真的不知道如何为这些关联制作初始迁移代码。

我是否必须使用 SQL 查询手动创建外键,或者是否有一些可用的方法?

【问题讨论】:

您想使用迁移来创建初始数据库结构,或者您想使用迁移来更新您当前的数据库结构? 我要先创建初始数据库结构 【参考方案1】:

案例 1:数据库初始化

如果您的目的是在数据库结构初始化期间添加关系,最好只使用sync 方法而不是使用迁移手动添加它们。如果您的模型设计正确并定义了关系,它们将在执行sync 方法期间自动创建。

看看sequelize express example。在模型目录中,您有三个文件:

index.js - 包括所有型号 task.js - 任务模型 user.js - 用户模型

查看task.js 内容,从第 7 行开始,以下代码创建了 User 和 Task 模型之间的关系:

classMethods: 
  associate: function(models) 
    Task.belongsTo(models.User, 
      onDelete: "CASCADE",
      foreignKey: 
        allowNull: false
      
    );
  

如果您在模型文件中正确准备了关系,同步将为您创建外键。在这种情况下不需要迁移。

我鼓励您阅读整个 express-example readme.md 并浏览存储库文件以了解这些内容如何与 express 和 sequelize 一起使用。

案例2:数据库结构迁移

如果您已经有一些想要保留的数据,则需要使用迁移脚本,因为同步重构数据库的唯一方法是将其与所有数据一起完全销毁。

您可以阅读基本的migrations in the sequelize docs。不幸的是,文档不包括创建关系。假设您要创建以下关系:用户属于组。要在关系的用户端创建列,您可以使用addColumn 方法。

queryInterface.addColumn(
  'user',
  'group_id',
  
    type: Sequelize.INTEGER,
    allowNull: true
  
)

不幸的是,还没有一个很好的函数来为您创建外键约束,但您可以使用 sequelize 查询方法手动完成。 Postgresql 示例:

queryInterface.sequelize.query("ALTER TABLE user
  ADD CONSTRAINT user_group_id_fkey FOREIGN KEY (group_id)
  REFERENCES group (id) MATCH SIMPLE
  ON UPDATE CASCADE ON DELETE CASCADE;");

编辑:添加数据库结构迁移案例

【讨论】:

嗯,好的,谢谢。我想我对迁移和同步之间的差异以及何时使用它们感到有些困惑。因此,如果我只使用 sync() 更新我的模型,它会正确迁移我的数据库吗? Sync 根据您当前的模型创建一个干净的数据库结构。如果 force 属性设置为 false,它只会在数据库不存在时创建数据库。否则每次重新启动服务器时它都会擦除整个数据库。迁移脚本用于通过对现有结构和数据进行操作来更改现有数据库。它在您希望在更新之间保留数据的生产环境中很有用。 投反对票,因为问题是专门关于迁移(生产需要),而这个答案没有回答这个问题。 (但sync 的答案很好)。 @ezrepotein 是的,这就是我目前正在做的事情。感谢您更新您的答案。非常讨厌我们必须这样做,功能在那里,但我不太确定如何将它拉出来。如果我找到更好的解决方案会回复。 从 17 年 5 月开始,您可以在迁移中创建外键约束。见这里:github.com/sequelize/cli/issues/239#issuecomment-166564364【参考方案2】:

将其添加为答案而不是上述@aryeh-armon 答案的评论(没有足够的代表)。这是您需要确保存在的表名,而不是模型名。即,如果您的模型名为 Job 并且您的 db 表名为 Jobs,那么迁移将看起来像这样。

jobId: 
type: Sequelize.INTEGER,
references: 
    model: "Jobs",
    key: "id"
  
,

【讨论】:

这是对 aryeh armon 答案的澄清(我同意,应该是评论),但我还没有足够的代表来评论其他用户的答案。【参考方案3】:

您可以添加对迁移的引用

示例:

user_id: 
    type: Sequelize.BIGINT,
    references: 
        model: "users",
        key: "id"
    
,

只要确保您引用的模型存在即可。

【讨论】:

【参考方案4】:

经过大量搜索,我找到了几篇解释我想做的博客文章。第一个已经不存在了,here's the second one

显然这不是真正的常用方法,但对我来说似乎更合乎逻辑。如果您只想使用迁移,则必须使用 SQL 查询来创建初始迁移。

但无论如何,我认为 ezpn 是正确的,它使用同步创建初始数据库,然后迁移。它似乎比使用 umzug 更容易并且只使用迁移。

【讨论】:

我同意最后一句话之前的一切。您需要迁移生产代码。 您能否详细说明使用迁移在生产环境中初始化数据库的可能用例? @ezrepotein sync 非常适合创建数据库,显然只是问题标题用更一般的(因此有用的)“Sequelize 迁移中的关联”来表述。我实际上更喜欢在生产中使用迁移,如果你也为你的测试数据库这样做,为什么不这样做。然后您的数据库设置和更新使用相同的声明性命令,例如sequelize db:migrate,而不是一些if no db, then db:sync, otherwise db:migrate 之类的东西。我认为人们普遍认为前者优于后者。 您描述的那些链接现在变成垃圾邮件,并重定向到随机页面!. @user8969730 谢谢!我认为第一个丢失了,但第二个 URL 似乎略有不同。自从我从事这个项目以来已经很长时间了,所以我无法描述我当时所做的事情,我能做的最好的就是更新链接,对不起。这可能已经过时了,请检查其他答案的 cmets。

以上是关于Sequelize 迁移中的关联的主要内容,如果未能解决你的问题,请参考以下文章

关联类方法中的现有字段 sequelize

删除 sequelize 迁移中的约束

使用 Sequelize 计算关联条目

如何通过节点js中的sequelize更新关联记录?

sequelize 是不是可以通过关联表中的属性过滤查询?

使用sequelize时如何自动创建迁移文件?