在 NodeJS 中序列化模型加载

Posted

技术标签:

【中文标题】在 NodeJS 中序列化模型加载【英文标题】:Sequelize model loading in NodeJS 【发布时间】:2018-09-03 22:08:35 【问题描述】:

我目前正在 Scotch.io 上学习使用 NodeJS、Express、PostgreSQL 和 Sequelize,然后我遇到了这个:

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var env       = process.env.NODE_ENV || 'development';
var config    = require(__dirname + '/../config/config.json')[env];
var db        = ;

if (config.use_env_variable) 
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
 else 
  var sequelize = new Sequelize(config.database, config.username, config.password, config);


fs
  .readdirSync(__dirname)
  .filter(function(file) 
    return (file.indexOf('.') !== 0) && (file !== basename) & (file.slice(-3) === '.js');
  )
  .forEach(function(file) 
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  );

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

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

module.exports = db;

我正在寻求对这段代码的通俗解释。这里到底发生了什么?

如果未设置 Node 环境,我确实了解我们默认为 development 的部分,但我需要澄清文件读取部分,即 fs 开始的位置。

【问题讨论】:

哇!非常感谢您的解释。现在清楚多了。还有一件事,这一行是做什么用的: var basename = path.basename(module.filename);? 我相信它只是从路径中删除文件名。如果您愿意,请查看***.com/questions/19811541/… 进行讨论。即我相信返回是index.js(假设文件名为index.js)。 非常感谢你!您的回复真的很有帮助。 太好了,乐于助人! 【参考方案1】:

首先,请注意,此代码由sequelize-cli 通过运行sequelize init 生成,并放置在models/ 文件夹中名为index.js 的文件中。

1.配置环境

if (config.use_env_variable) 
  var sequelize = new Sequelize(process.env[config.use_env_variable]);
 else 
  var sequelize = new Sequelize(config.database, config.username, config.password, config);

这对生产时很有帮助。作为示例,我将向您展示我的代码:

module.exports = 
  development: 
    dialect: 'postgres',
    username: '<username name>',
    password: 'test',
    database: '<db name>',
    host: 'localhost'
  ,
  production: 
    dialect: 'postgres',
    dialectOptions: 
      ssl: true
    ,
    protocol: 'postgres',
    use_env_variable: 'DATABASE_URL'
  

Heroku 设置了一个流程变量DATABASE_URL,我只是指向它。用户名、密码等都是从中获取的,而不是像开发凭据那样在config.js 中明确列出。

2。导入/读取模型

fs
  .readdirSync(__dirname)
  .filter(function(file) 
    return (file.indexOf('.') !== 0) && (file !== basename) & (file.slice(-3) === '.js');
  )
  .forEach(function(file) 
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  );

fs.readdirSync 同步读取其参数中给出的目录。在这种情况下,它是__dirname,也就是这个 index.js 文件所在的目录。这里,你在models/ 目录中定义的模型被拉进来。注意过滤函数只是确保:

有文件要读 它排除了这个文件(即不是index.js) 它们以“.js”结尾

然后将每个模型文件键入到带有 db[model.name] = model; 行的导出对象中

3.关联每个模型

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

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

module.exports = db;

最后,一旦我们获得了所有的模型文件(从之前的读取),我们运行每个模型的associate 函数,如果它存在的话。这是在每个模型文件中定义的方法如下:

module.exports = (sequelize, DataTypes) => 
  var Model1 = sequelize.define('Model1',
     ... )

  // Class Method
  Model1.associate = function (models) 
    Model1.belongsTo(models.Model2)
  
  return Model1

4.出口使用

您的 sequelize 数据库 (sequelize) 的实例和 Sequelize 库的实例都被导出。

通过这种方式,我们现在可以执行以下操作:

假设目录结构为

型号/ index.js model1.js model2.js

require('./models').Model1 // access to your models

这是您导入和使用模型的方式,而不是直接通过它们的定义文件。这可确保它们正确同步和关联。

同样我们可以访问 sequelize:

require('./models')
  .sequelize.sync( force: true ) // access to your sequelize db

【讨论】:

您的config.json.gitignore 中吗? @keshavAggarwal 否 - 签入.config.json 是安全的。如果您不希望公开开发凭据,请使用环境变量。常用的包是dotenv应该忽略.env文件。【参考方案2】:

简单来说,这是从与此文件相同的目录中导入所有.js 文件。这是通过sequelize['import'] 方法完成的。

此外,假设所有这些文件都包含续集模型,因为导入的返回值映射到名为 db 的字典上。

db[model.name] = model

导入所有文件并将模型映射到db 后,将运行循环以在每个模型上调用associate,前提是该模型包含关联方法。通常使用 associate 方法来定义模型之间的所有关联,即hasManyhasOnebelongsTo 等。

【讨论】:

太棒了!谢谢。

以上是关于在 NodeJS 中序列化模型加载的主要内容,如果未能解决你的问题,请参考以下文章

stanford coreNLP CRFClassifier 模型加载和序列化

保存和加载模型

SPSS时间序列 应用时间序列模型

Pytorch加载和保存模型

Pytorch 模型的存储与加载

推荐收藏保存和加载机器学习模型的这两个方法不错