Sequelize 6 从文件中导入模型

Posted

技术标签:

【中文标题】Sequelize 6 从文件中导入模型【英文标题】:Sequelize 6 import models from file 【发布时间】:2020-10-14 19:20:36 【问题描述】:

我想知道如何使用 ?

它适用于“续集”:“^5.22.0”, "sequelize-cli": "^5.5.1",但我在使用 Sequelize 6 时出错。

目前,我有这个:

数据库/setup/databaseConnection.js

// Imports
import  Sequelize  from "sequelize"

const connection = new Sequelize(
    process.env.DATABASE_NAME,
    process.env.DATABASE_USER,
    process.env.DATABASE_PASSWORD,
    
        host: process.env.DATABASE_URL,
        port: process.env.DATABASE_PORT,
        dialect: "mysql",
        logging: false,
        define: 
            // prevent sequelize from pluralizing table names
            freezeTableName: true,
        ,
    
)

// Test connection
console.info("SETUP - Connecting database...")

connection
    .authenticate()
    .then(() => 
        console.info("INFO - Database connected.")
    )
    .catch((err) => 
        console.error("ERROR - Unable to connect to the database:", err)
    )

export  connection as default 

数据库/模型/index.js

// Imports
import Sequelize from "sequelize"

// App Imports
import connection from "../setup/databaseConnection"

const models = 
    Language: connection.import("./language"),


Object.keys(models).forEach((modelName) => 
    if ("associate" in models[modelName]) 
        models[modelName].associate(models)
    
)

models.sequelize = connection
models.Sequelize = Sequelize

export  models as default 

数据库/模型/语言.js

module.exports = (sequelize, DataTypes) => 
    const Language = sequelize.define(
        "language",
        
            /* id       : 
         primaryKey: true,
         type      : DataTypes.INTEGER
         , */
            name: 
                type: DataTypes.STRING,
            ,
            code: 
                type: DataTypes.STRING,
            ,
            is_active: 
                type: DataTypes.BOOLEAN,
            ,
        ,
        
    )
    Language.associate = function (models) 
        // Language has Many Bucket
        models.Language.hasMany(models.Bucket, 
            foreignKey: "id",
        )
    
    return Language

但我有这个错误:

formation-api/database/models/index.js:17
  Language: _databaseConnection["default"]["import"]("./language")
                                                    ^

TypeError: _databaseConnection.default.import is not a function
    at Object.<anonymous> (/Users/jeremiechazelle/Sites/api/database/models/index.js:8:15)
    at Module._compile (internal/modules/cjs/loader.js:1147:30)
    at Module._compile (/Users/jeremiechazelle/Sites/api/node_modules/pirates/lib/index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:1167:10)
    at Object.newLoader [as .js] (/Users/jeremiechazelle/Sites/api/node_modules/pirates/lib/index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:996:32)
    at Function.Module._load (internal/modules/cjs/loader.js:896:14)
    at Module.require (internal/modules/cjs/loader.js:1036:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (/Users/jeremiechazelle/Sites/api/resolvers/Queries/User.js:2:1)
[nodemon] app crashed - waiting for file changes before starting...

我使用: "续集": "^6.1.0", "sequelize-cli": "^6.0.0"

【问题讨论】:

【参考方案1】:

Sequelize ^6.x 不再支持 sequelize.import。他们说你应该使用 require 来代替。

我了解到您必须手动导入模型。

这里是一个使用 require 的例子

./models/index.js

const dotenv = require('dotenv');
const fs = require('fs');
const path = require('path');
const  Sequelize, DataTypes  = require('sequelize');

const filebasename = path.basename(__filename);
const db = ;

// Get env var from .env
dotenv.config()
const  DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_FORCE_RESTART  = process.env;

const config = 
  host: DB_HOST,
  dialect: 'mysql',
  dialectOptions: 
    charset: 'utf8',
  


const sequelize = new Sequelize(DB_NAME, DB_USER, DB_PASS, config);

fs
  .readdirSync(__dirname)
  .filter((file) => 
    const returnFile = (file.indexOf('.') !== 0)
      && (file !== filebasename)
      && (file.slice(-3) === '.js');
    return returnFile;
  )
  .forEach((file) => 
    const model = require(path.join(__dirname, file))(sequelize, DataTypes)
    db[model.name] = model;
  );


Object.keys(db).forEach((modelName) => 
  if (db[modelName].associate) 
    db[modelName].associate(db);
  
);

db.sequelize = sequelize;
db.Sequelize = Sequelize;

const sequelizeOptions =  logging: console.log, ;

// Removes all tables and recreates them (only available if env is not in production)
if (DB_FORCE_RESTART === 'true' && process.env.ENV !== 'production') 
  sequelizeOptions.force = true;


sequelize.sync(sequelizeOptions)
  .catch((err) => 
    console.log(err);
    process.exit();
  );

module.exports = db;

./models/User.js

'use strict';

import cryp from 'crypto';

module.exports = function (sequelize, DataTypes) 
  const User = sequelize.define('User', 
    email: 
      type: DataTypes.STRING(50),
      allowNull: false,
      unique: true,
      validate: 
        isEmail:  msg: "Please enter a valid email addresss" 
      ,
      isEmail: true
    ,
    password_hash:  type: DataTypes.STRING(80), allowNull: false ,
    password: 
      type: DataTypes.VIRTUAL,
      set: function (val) 
        //this.setDataValue('password', val); // Remember to set the data value, otherwise it won't be validated
        this.setDataValue('password_hash', cryp.createHash("md5").update(val).digest("hex"));
      ,
      validate: 
        isLongEnough: function (val) 
          if (val.length < 8) 
            throw new Error("Please choose a longer password");
          
        
      
    ,
    role: 
      type: DataTypes.INTEGER,
      allowNull: false
    ,
    active: 
      type: DataTypes.INTEGER,
      allowNull: false,
      defaultValue: 1
    

  , 
    classMethods: 
      associate: function (models) 
        // User.belongsTo(models.Department,  foreignKey:  allowNull: false  );
        // User.belongsTo(models.Position,  foreignKey:  allowNull: false  );
        // User.belongsTo(models.Profile,  foreignKey:  allowNull: false  );

        // User.hasMany(models.Report,  foreignKey:  allowNull: false  );
        // User.hasMany(models.Notification,  foreignKey:  allowNull: false  );
        // User.hasMany(models.Response,  foreignKey:  allowNull: false  );

      
    ,

    timestamps: true,

    // don't delete database entries but set the newly added attribute deletedAt
    // to the current date (when deletion was done). paranoid will only work if
    // timestamps are enabled
    paranoid: false,

    // don't use camelcase for automatically added attributes but underscore style
    // so updatedAt will be updated_at
    underscored: true
  );
  return User;
;

.env

DB_HOST=localhost
DB_USER=wilo087
DB_PASS=temp
DB_NAME=database_name
DB_FORCE_RESTART=true #Remove and create tables

完整示例: https://github.com/wilo087/pethome_raffle_backend/tree/develop

【讨论】:

谢谢@wilo087 的回答,请问有代码示例吗? 很遗憾,您不能在带有 ES 模块的最新 Node 版本中使用“require”。【参考方案2】:

像这样:

import Sequelize from 'sequelize'

import userModel from './user'
import messageModel from './message'

const sequelize = new Sequelize(process.env.DATABASE, process.env.DATABASE_USER, process.env.DATABASE_PASSWORD, 
    dialect: 'postgres'
)

const models = 
    User: userModel(sequelize, Sequelize.DataTypes),
    Message: messageModel(sequelize, Sequelize.DataTypes)

【讨论】:

【参考方案3】:

我遇到了同样的问题并解决了:

版本 5.25.1 const model = sequelize["import"](path.join(__dirname, file));

版本 6.2.1 const model = require(path.join(__dirname, file))(sequelize, Sequelize);

希望对你有帮助

【讨论】:

【参考方案4】:

我试图找到一种方法来使用类定义的方式来做到这一点。我就是这样做的!

models/trading-view-alert.js

const  Model, DataTypes  = require('sequelize');
module.exports = function(sequelize)
    class TradingViewAlert extends Model 
    return TradingViewAlert.init(
      action: 
          type: DataTypes.STRING,
          allowNull: false
      ,
      strategy_num_contracts: 
          type: DataTypes.STRING,
          allowNull: false
      ,
      strategy_orderid: 
          type: DataTypes.STRING,
          allowNull: false
      ,
      strategy_price: 
          type: DataTypes.STRING,
              allowNull: false
          ,
      strategy_comment : 
          type: DataTypes.STRING,
          allowNull: false 
      ,
      strategy_position_size: 
          type: DataTypes.STRING,
          allowNull: false  
      
    , 
      sequelize,
      modelName: 'TradingViewAlert'
    );
;

你的文件使用了model.js

const TradingViewAlert = require('../models/trading-view-alert');
const TradingViewAlertModel = TradingViewAlert(sequelize);

然后只需调用 await TradingViewAlertModel.sync( alter: true );

sync 命令当然需要在 async() 函数中才能工作,然后就可以使用带有 sequelize 6 的类和单独的文件中的模型!

【讨论】:

【参考方案5】:

如果你有很多模型,写一个导入方法可能会很有用:

const autoImport = function(path) 
  let defineCall = require(path);
  if (typeof defineCall === 'object' && defineCall.__esModule) 
    // Babel/ES6 module compatability
    defineCall = defineCall['default'];
  
  return defineCall(sequelize, Sequelize.DataTypes);
;

所以不要这样:

...

const models = 
    Language: connection.import("./language"),


...

你可以这样做:

...

const models = 
    Language: autoImport("./language"),

...

拥有 50 多个模型,我们更容易迁移到 Sequelize 6。

【讨论】:

以上是关于Sequelize 6 从文件中导入模型的主要内容,如果未能解决你的问题,请参考以下文章

了解 Sequelize 中的关联

为啥 Sequelize 在 3120 条记录后会暂停?

使用 Sequelize.js 进入包含模型

使用 Typescript 在 Sequelize 模型中创建实例方法

更改数据库模型 - Sequelize

Confluence 6 从一个 XML 备份中导入一个空间