【问题标题】:Using Sequelize with associations and scopes with includes in multiple files将 Sequelize 与关联和范围一起使用,并包含在多个文件中
【发布时间】:2016-03-28 04:58:12
【问题描述】:

我使用this way 将我的 Sequelize 模型保存在单独的文件中,并且一切正常,但现在我想出了在其中包含包含范围的想法。

这样的事情是行不通的:

var User = sequelize.define("User", {...}, {
  scopes: {
    complete: {
      include: [{
        model: Task
      }]
    }
  }
});

... 因为 Task (当然)没有定义。即使使用 require('.').Task 在这一点上也无济于事,因为 UserTask 之前加载,而在加载 User 时,Task 尚未定义。

那么,有没有一种简单易行的方法,无需十几种变通方法

  • 关联
  • 包含的范围
  • ...所有这些都在每个模型的单独文件中?

【问题讨论】:

  • 我几乎不得不编写自己的依赖注入模块来处理这个问题。 Sequelize 可能是目前 node 最好的 ORM 映射器,但在很多领域严重缺乏,IMO

标签: node.js sequelize.js


【解决方案1】:

尝试使用Sequelize.models.Task

module.export = function(Sequelize, DataTypes){
  var User = sequelize.define("User", {...}, {
    scopes: {
      complete: {
        include: [{
          model: Sequelize.models.Task
        }]
      }
    }
  });
}

或者使用addScope()添加它们而不必担心加载每个模型的顺序

【讨论】:

  • 工作正常,太棒了!谢谢!
  • @ManuelBieh 没问题!我很高兴能帮上忙 =)
  • 嗯……不完全是:(模型的加载顺序似乎仍然存在问题。我正在加载按字母顺序排列的模型文件。当我将Task重命名为时,让说Zask,我收到一个错误,因为Zask 现在加载之后 UserCannot read property 'getTableName' of undefined。似乎无法解决。
  • 哎呀,明白了!有一个方法addScope(),可以和例子中的associate方法一样使用。
【解决方案2】:

如果模型(任务)尚未加载? (在这种情况下,T 在 U 之前,并且模型已加载)。

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

变成

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

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

和模型

module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define("User", {
    username: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        User.hasMany(models.Task)
      }
    }
  });

  return User;
};

变成

module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define("User", {
    username: DataTypes.STRING
  }, {
    classMethods: {
      associate: function(models) {
        User.hasMany(models.Task)
      }

      loadScopes: function(models) {
        User.addScope('complete', {
          include: [{
            model: models.Task
          }]
        })
      }

    }
  });

  return User;
};

【讨论】:

    【解决方案3】:

    使用addScope() 方法更适合将模型包含在范围内。这是因为 Sequelize 模型是按字母顺序定义的,Model A 先于 Model B。当您在 Model A 范围内包含 Model B 时,到 Model A 运行时 Model B 未定义。 addScope() 方法解决了这个问题。

    module.exports = function(sequelize, DataTypes) {
      const User = sequelize.define('User', {
        username: DataTypes.STRING
      }, { });
    
      User.associate = function(models) {
        // associations can be defined here
        User.hasMany(models.Task);
    
        // scopes should be defined here
        User.addScope('defaultScope', {
          include: [{ model: models.Task }],
        });
    
        // scopes with parameter
        User.addScope('byProfile', profileId => ({
          where: { profileId },
        }));
      };
    
      return User;
    };
    

    使用默认范围:

    User.findAll(); 这将默认使用默认范围。

    使用byProfile 作用域:

    User.scope({ method: ['byProfile', profile.id] }).findAll();

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2020-01-01
    • 2019-04-12
    • 2018-07-13
    • 1970-01-01
    • 2017-10-27
    • 2018-11-13
    相关资源
    最近更新 更多