Sequelize 模型关联不会创建新列

Posted

技术标签:

【中文标题】Sequelize 模型关联不会创建新列【英文标题】:Sequelize model association won't create a new column 【发布时间】:2020-08-25 18:56:27 【问题描述】:

为什么在我的某些模型中,sequelize 不会为 foreignkey 创建新列?但它确实为其他模型创建???这令人沮丧和奇怪。例如,在这个 User 模型中,sequelize 不会创建 role_id

'use strict';
module.exports = (sequelize, DataTypes) => 
  const User = sequelize.define('User', 
    id:  type: DataTypes.BIGINT, allowNull: false, autoIncrement: true, unique: true, primaryKey: true ,
    first_name: DataTypes.STRING,
    last_name: DataTypes.STRING
  , );
  User.associate = function(models) 
    User.belongsTo(models.Role,  foreignKey: 'role_id' );
  ;
  return User;
;

这是一个类似的问题:Sequelize not creating model association columns 但是!没有人回答。

我花了几个小时在这上面,我做了所有的事情:

    彻底阅读:https://sequelize.org/master/manual/assocs.html 进行实验,例如创建一个名为 NewUser 的新虚拟模型。有用!但同样不是User 名称。 发布在 Sequelize 的 Slack 频道上。

在这个 *** 问题之后,我会从他们的 Github 问题页面寻求帮助。

我想我可以只定义列 role_id 而不是通过 associate 函数添加它。

【问题讨论】:

您能否展示已创建 FK 的模型与未创建 FK 的模型之间的差异?这两种型号的注册流程有区别​​吗? 嘿安托利,根本没有区别!就像我提到的那样,我尝试创建一个内容相同但文件名不同的虚拟模型,例如ZUser.js(模型定义为ZUser,我可以看到Sequelize 添加了roldeId 列。我现在真的不知道发生了什么。我认为是因为类名定义为User???? 也许当您运行“同步”时,用户表已经存在并且 sequelize 不会改变它,而新的 ZUser 模型会导致创建一个包含所有列和 FK 的新表跨度> 我在开发/本地时确实同步强制为真。像这样:db.sequelize.sync( force : true)。我也尝试过删除所有表(但没有尝试重新创建数据库)。我还尝试删除迁移,然后重新运行 db:migrate/ 等等!您可以使用“同步”或迁移,但不能同时使用! 【参考方案1】:

所有模型都应该在一个地方注册,只要它们的关联:

数据库.js

const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const db = 
const models = path.join(__dirname, 'models') // correct it to path where your model files are

const sequelize = new Sequelize(/* your connection settings here */)

fs
  .readdirSync(models)
  .filter(function (file) 
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')
  )
  .forEach(function (file) 
    // Sequelize version <= 5.x
    var model = sequelize['import'](path.join(models, file))
    // Sequelize version >= 6.x
    // var model = require(path.join(models, file))(
    //   sequelize,
    //   Sequelize.DataTypes
    // );
    db[model.name] = model;
  )

Object.keys(db).forEach(function (modelName) 
  if (db[modelName].associate) 
    db[modelName].associate(db)
  
)

db.Sequelize = Sequelize // for accessing static props and functions like Op.or
db.sequelize = sequelize // for accessing connection props and functions like 'query' or 'transaction'

module.exports = db

some_module.js

const db = require('../database')
...
const users = await db.user
   .findAll(
     where: 
      [db.Sequelize.Op.or]: [
        first_name: 'Smith'
      , 
        last_name: 'Smith'
      ]
     
)

【讨论】:

谢谢,阿纳托利。但我觉得我做的没错,因为这个注册的东西也是由 Sequelize 生成的!解决方案实际上是在db.sync之后注册路由。 basename 变量从何而来? var basename = path.basename(module.filename) @Anatoly 我可以看到TypeError: sequelize.import is not a function @Anatoly 同时,我浏览了一些类似的帖子。我试图合并这些。但是一些小错误阻止了我。您有什么建议可以参考任何完整的示例代码吗?【参考方案2】:

感谢 Anatoly 一直关注我关于 Sequelize 的问题。

经过这么多尝试和错误,我认为问题是由我的路线注册引起的,例如:

require("./app/routes/user/user.routes")(app)

在我的 app.jsserver.js 中。这些路由注册是在db.sync之前添加的!

所以我的做法是,在 db.sync 之后将这些路由注册称为:

const db = require("./app/models")

if (process.env.NODE_ENV === "production") 
  db.sequelize.sync().then(() => 
    useRoutes()
  )
 else 
  db.sequelize.sync( force: true ).then(() => 
    console.log("Drop and re-sync db.")
    useRoutes()
  )


function useRoutes() 
  console.log("Use routes...")
  require("./app/routes/user/user.routes")(app)
  require("./app/routes/auth/auth.routes")(app)

瞧,修复了!

【讨论】:

以上是关于Sequelize 模型关联不会创建新列的主要内容,如果未能解决你的问题,请参考以下文章

了解 Sequelize 中的关联

Sequelize 从 belongsTo 关系中获取值

更改数据库模型 - Sequelize

在 Sequelize 中从关联创建复合主键

如何在 Sequelize CLI 中添加、删除新列

Sequelize models - 在 Node 中同步时设置关联