如何组织使用sequelize的节点应用?

mko*_*yak 120 node.js express sequelize.js

我正在寻找一个使用sequelize ORM的示例nodejs应用程序.

我主要担心的是,如果这些模型由于require()依赖循环而彼此之间具有复杂的关系,那么几乎不可能在单独的js文件中定义模型.也许人们将所有模型定义在一个非常长的文件中?

我主要感兴趣的是如何定义模型并在整个应用程序中使用.我希望得到一些验证,我自己所做的是做事的"好"方式.

use*_*770 122

短篇小说

在这种情况下的技巧不是初始化文件中的模型,而只是为其初始化提供必要的信息,让集中模块负责模型设置和实例化.

所以步骤是:

  • 有几个模型文件包含有关模型的数据,如字段,关系和选项.
  • 有一个单独的模块,可以加载所有这些文件并设置所有模型类和关系.
  • 在app.js文件中设置单例模块.
  • 获得从单模块模型类使用require来自单上的模型文件,加载型号代替使用.

更长的故事

以下是此解决方案的更详细说明以及相应的源代码:

http://jeydotc.github.io/blog/2012/10/30/EXPRESS-WITH-SEQUELIZE.html

编辑:这是一个非常古老的答案!(阅读信息)

它在很多方面都很老旧而有限!

  • 首先,正如@jinglesthula在评论中提到的那样(我也经历过) - 需要这些文件存在问题.这是因为require不同的方式readdirSync!

  • 第二 - 你的关系非常有限 - 代码不提供这些关联的选项,所以你无法创建belongsToMany它需要的through属性.您可以创建最基本的关联.

  • 第三 - 你在模特关系方面非常有限!如果你仔细阅读代码,你会发现关系是一个Object而不是一个数组,所以如果你想创建多个相同类型的关联(比如有两次belongsTo) - 你就不能!

  • 第四 - 你不需要那个单身的东西.nodejs中的每个模块本身都是单例,因此所有这些都是无关紧要的.

你应该看到Farm的答案!(该文章的链接已被破坏,但我将使用sequelize中的官方示例修复它:https://github.com/sequelize/express-example/blob/master/models/index.js - 您可以浏览整个项目,以了解正在发生的事情).

ps我正在编辑这篇文章因为它如此受欢迎,以至于人们甚至都看不到任何新的答案(正如我所做的那样).

编辑:刚刚将链接更改为同一帖子的副本,但在Github页面中

  • 因此,可以通过删除单例棘手的部分来简化示例,只需将module.exports = new OrmClass().我会尝试一下,谢谢你的反馈:) (2认同)
  • 万一有人头疼我,我会救你的.我遇到了github文章中列出的以路径为中心的代码的问题.我不得不添加一个.to the require(如下所示:var object = require('.'+ modelsPath +"/"+ name);)并在init函数的forEach中输入name.indexOf('DS_Store')> -1的返回值(是的OSX).希望有所帮助. (2认同)

Far*_*arm 93

SequelizeJS在他们的网站上有一篇文章解决了这个问题.

链接已损坏,但您可以在此处找到工作示例项目并进行浏览.请参阅上面编辑的答案,了解为什么这是更好的解决方案.

文章摘录:

  • 车型/ index.js

    此文件的想法是配置与数据库的连接并收集所有模型定义.一切就绪后,我们将调用每个模型上关联的方法.此方法可用于将模型与其他模型相关联.

          var fs        = require('fs')
            , path      = require('path')
            , Sequelize = require('sequelize')
            , lodash    = require('lodash')
            , sequelize = new Sequelize('sequelize_test', 'root', null)
            , db        = {} 
    
          fs.readdirSync(__dirname)
            .filter(function(file) {
              return (file.indexOf('.') !== 0) && (file !== 'index.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].options.hasOwnProperty('associate')) {
              db[modelName].options.associate(db)
            }
          })
    
          module.exports = lodash.extend({
            sequelize: sequelize,
            Sequelize: Sequelize
          }, db)
    
    Run Code Online (Sandbox Code Playgroud)

  • 这就是Sequelize建议的方式.我会接受这个作为正确的答案. (12认同)
  • 这很好,但你不能使用其他模型的实例方法中的模型,或者我可能错过了一些东西. (3认同)
  • @mlkmt你可以!由于您可以访问模型文件中的`sequelize`变量,因此可以使用`sequelize.models.modelName`访问其他模型. (3认同)

jsp*_*iri 27

我创建了一个包sequelize-connect来帮助人们处理这个问题.它遵循Sequelize建议的惯例:http://sequelize.readthedocs.org/en/1.7.0/articles/express/

此外,就其界面而言,它的功能更像Mongoose.它允许您指定模型所在的一组位置,还允许您定义自定义匹配函数以匹配模型文件.

用法基本上是这样的:

var orm = require('sequelize-connect');

orm.discover = ["/my/model/path/1", "/path/to/models/2"];      // 1 to n paths can be specified here
orm.connect(db, user, passwd, options);                        // initialize the sequelize connection and models
Run Code Online (Sandbox Code Playgroud)

然后你可以访问模型和sequelize如下:

var orm       = require('sequelize-connect');
var sequelize = orm.sequelize;
var Sequelize = orm.Sequelize;
var models    = orm.models;
var User      = models.User;
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人.

  • 链接到文章有点帮助.引用一些文档更好.显示代码片段很棒....但实际上构建一个解决问题并将其放在NPM上的库是非常棒的**,值得更多的爱!+1并将为您的项目加注星标. (3认同)

mvb*_*fst 9

我开始在Express.js应用程序中使用Sequelize.很快就遇到了你所描述的性质问题.也许我不太了解Sequelize,但对我来说,做事不仅仅是从一张桌子中选择并不是很方便.通常你会在两个或多个表中使用select,或者在纯SQL中使用union,你必须运行单独的查询,并且由于Node的异步性质,它只是增加了复杂性.

因此我放弃了使用Sequelize.此外,我正在从模型中使用从数据库中获取的任何数据进行切换.在我看来,抽象获取数据更好.原因是 - 假设您不仅使用MySQL(在我的情况下,我并排使用MySQL和MongoDB),但您可以从任何数据提供程序和任何传输方法获取数据,例如SQL,no-SQL,文件系统,外部API,FTP,SSH等.如果您尝试在模型中完成所有这些操作,最终会创建难以升级和调试的复杂且难以理解的代码.

现在,你想要做的是有机型从知道在哪里以及如何获得它一个层中获取数据,但您的模型只使用API的方法,例如fetch,save,delete等这层内你有具体的数据提供商的具体实现.例如,您可以从本地计算机上的PHP文件或Facebook API或Amazon AWS或远程HTML文档等请求某些数据.

PS一些想法是从借来的设计师通过CLOUD9:http://events.yandex.ru/talks/300/


jac*_*cob 5

我将其设置为Farm并在文档中进行了描述。

但是我遇到了一个附加的问题,即在我要附加到每个函数中的模型的实例方法和类方法中,我需要要求索引文件才能拥有其他数据库对象。

通过使所有模型都可以访问它们来解决此问题。

var Config = require('../config/config');

 var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var _ = require('lodash');
var sequelize;
var db = {};

var dbName, dbUsername, dbPassword, dbPort, dbHost;
// set above vars

var sequelize = new Sequelize(dbName, dbUsername, dbPassword, {
dialect: 'postgres', protocol: 'postgres', port: dbPort, logging: false, host: dbHost,
  define: {
    classMethods: {
        db: function () {
                    return db;
        },
        Sequelize: function () {
                    return Sequelize;
        }

    }
  }
});


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

Object.keys(db).forEach(function(modelName) {
  if ('associate' in db[modelName]) {
      db[modelName].associate(db);
  }
});

module.exports = _.extend({
  sequelize: sequelize,
  Sequelize: Sequelize
}, db);
Run Code Online (Sandbox Code Playgroud)

并在模型文件中

var classMethods = {
  createFromParams: function (userParams) {
    var user = this.build(userParams);

    return this.db().PromoCode.find({where: {name: user.promoCode}}).then(function (code) {
        user.credits += code.credits;
                return user.save();
    });
  }

};

module.exports = function(sequelize, DataTypes) {
  return sequelize.define("User", {
  userId: DataTypes.STRING,
}, {  tableName: 'users',
    classMethods: classMethods
 });
};
Run Code Online (Sandbox Code Playgroud)

我只对类方法这样做,但是您也可以对实例方法做同样的事情。