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

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

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

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

【问题讨论】:

  • 您想使用迁移来创建初始数据库结构,或者您想使用迁移来更新您当前的数据库结构?
  • 我要先创建初始数据库结构

标签: node.js associations database-migration sequelize.js


【解决方案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。
    猜你喜欢
    • 2019-04-16
    • 2017-06-26
    • 2021-08-06
    • 2015-10-05
    • 2015-02-15
    • 2016-03-01
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多