在预先存在的数据库上定制多对多的热切加载

时间:2014-04-03 20:18:10

标签: mysql many-to-many eager-loading sequelize.js

我正在尝试使用Sequelize设置我现有的Express应用程序。在应用程序中,在用户登录时,我执行查询以尝试获取表示用户的对象以及来自少数几个表的几个关系。我已经使用多对多关系将我的测试下拉到以下最小化表示。

这是我的用户模型(在coffeescript中):

module.exports = (sequelize, DataTypes) ->
  sequelize.define "User",
    id:
      type: DataTypes.INTEGER(11)
      primaryKey: true
      autoIncrement: true

    email:
      type: DataTypes.STRING
      allowNull: false

  ,
    tableName: 'users'
    classMethods:
      associate: (models) ->
        @hasOne models.UserDetail
        @hasMany models.Plan,
          through: models.UserPlan
          foreignKey: 'user_id'

这是我的计划模型:

module.exports = (sequelize, DataTypes) ->
  sequelize.define "Plan",
    id:
      type: DataTypes.INTEGER(11)
      primaryKey: true
      autoIncrement: true

    plan:
      type: DataTypes.STRING
      allowNull: false
  ,
    tableName: 'plans'
    classMethods:
      associate: (models) ->
        @hasMany models.User,
          through: models.UserPlan
          foreignKey: 'plan_id'

而且,这是中间的“通过”表(user_plans):

module.exports = (sequelize, DataTypes) ->
  sequelize.define "UserPlan",
    user_id:
      type: DataTypes.INTEGER(11)
      allowNull: false
      primaryKey: true

    plan_id:
      type: DataTypes.INTEGER(11)
      allowNull: false
  ,
    tableName: 'user_plans'

以下是我正在执行的发现,我希望能够实现这一目标:

          console.log JSON.stringify(u)
          db.User.find(
            where:
              id: u.id
            include: [
                model: db.Plan
                as: 'plan'
            ]
          )
          .success (user) ->
            console.log JSON.stringify(user)

在这种情况下,我有一个非急切的加载对象'u'被删除到控制台,但后来查询.success调用永远不会发生,所以'user'对象永远不会被转储到控制台。这是输出:

{"id":3,"email":"asdf@1234.com"}
[Error: Plan (plan) is not associated to User!]

知道我可能做错了吗?一些讨论显示,这可能是过去使用现有表格的问题,但看起来这些问题已在最新版本的sequelize中得到解决。我正在运行~1.7.0(在撰写本文时最新)。

感谢任何帮助。

1 个答案:

答案 0 :(得分:9)

as in包含指定别名。设置关联时也必须设置此别名。

几个例子:

User.hasMany(Plans) 
User.find({
  include: [
    { model: Plan }  // no as is allowed here, since we didnt specify it in the association
  ]
})

User.hasMany(Plans, { as: 'plans' }) 
User.find({
  include: [
    { model: Plan, as: 'plans' } // here you HAVE to specify the same alias as you did in your association
  ]
})

作为一个更高级的示例,显示为什么必要,考虑多次关联相同的模型:

User.belongsTo(Plans, { as: 'currentPlans' }) // this is joined via planId on user
User.hasMany(Plans, { as: 'previousPlans' }) // this is stored in a join table
Plan.hasMany(User)

User.find({
  include: [
    { model: Plan } 
      /* If you dont specify an as here, sequelize has no way of knowing which 
         relation to load. Therefore the as should only be provided if you 
         set one in the association, and you should provide the exact same
         string as in the assocation.
      */ 
  ]
})