【问题标题】:Sequelize.js - choosing the right relationshipSequelize.js - 选择正确的关系
【发布时间】:2021-01-06 15:22:32
【问题描述】:

我正在使用 NodeJS 并进行续集。 我有一个名为duel_id 的列的用户表,每个用户一次可以分配到一个决斗。 每个决斗可以有多个用户。

我有以下用户模型:

const User = Model.define(
  'User',
  {
    user_id: {
      type: DataType.INTEGER,
      primaryKey: true,
    },

    username: {
      type: DataType.STRING(255),
    },
    character: {
      type: DataType.INTEGER,
    },
    duel_id: {
      type: DataType.INTEGER,
    },
  },
  {
    indexes: [{ fields: ['user_id', 'username'] }],
    tableName: 'users',
    timestamps: false,
  },
);

User.hasOne(Duel, { as: 'duel', foreignKey: 'id', sourceKey: 'duel_id' });

使用以下决斗模型:

const Duel = Model.define(
  'DuelRoom',
  {
    id: {
      type: DataType.INTEGER,
      primaryKey: true,
      autoIncrement: true,
    },
    round_id: {
      type: DataType.INTEGER,
    },
    status: {
      type: DataType.STRING,
    },
    turn_of_user_id: {
      type: DataType.INTEGER,
    },
    winner: {
      type: DataType.STRING,
    },
  },
  {
    indexes: [{ fields: ['id'] }],
    tableName: 'duel_rooms',
    timestamps: true,
  },
);

上面的代码有效,如果他有一个用户和相关的决斗,则返回。

我还想将所有关联到同一个决斗的用户返回。

我尝试将关系与hasMany/belongsTo 联系起来,但没有成功。出现以下错误:

Error: DuelRoom.hasMany called with something that's not a subclass of Sequelize.Model

我希望能够查询得到这样的数据:

user: { 
   user_id,
   username
   duel: {
      round_number
      players: [{user_id, username}]
   }
}

获取当前用户的决斗信息,所有玩家都与同一个duel_id 关联为一个名为players 的数组。

知道如何使用 sequelize 定义这种关系以返回与用户决斗相关的所有用户吗?

【问题讨论】:

    标签: node.js orm sequelize.js


    【解决方案1】:

    因为每个用户都可以进行一场决斗,而一场决斗可以与多个用户相关联。这是一个一对多的关联,所以,你应该尝试:

    Duel.hasMany(User);
    User.belongsTo(Duel);
    

    【讨论】:

      【解决方案2】:

      如果 User 模型有 dual_id,那么您应该在 User 到 DualRoom 中使用 belongTo 而不是 hasOne

      User.belongsTo(Duel, { as: 'duel', foreignKey: 'duel_id' });
      

      如果您希望在 Duel 模型中收集用户,那么这将适用于以下 hasMany

      Duel.hasMany(User, { as: 'users', foreignKey: 'duel_id' });
      

      考虑到您应该在所有模型注册之后注册所有关联,就像我在 this answer 中建议的那样

      完成所有这些设置后,您可以通过执行如下查询得到您想要的:

      const user = await User.findOne({
        where: {
           user_id: id
        },
        include: [{
          model: Duel,
          as: 'duel',
          include: [{
            model: User,
            separate: true,
            as: 'users'
          }]
        }]
      })
      

      【讨论】:

      • 谢谢,但是我如何导入UserDuel,它会创建一个循环依赖并返回未定义,因为尚未定义相关模型,知道吗?
      • 你看到我的答案了吗,我给你的链接stackoverflow.com/questions/61709290/…
      • 我看了看,如果我需要重构我所有的 sequelize 代码并添加代码来扫描目录和文件只是为了使关系在 ORM 中工作,我宁愿不使用它。谢谢。
      • 如果您不想扫描目录,可以在一个模块中手动注册模型和关联,显式导入它们。
      • 如果您希望将某些决斗的用户命名为 players,那么只需将别名重命名为 Duel.hasMany(User, { as: 'players', foreignKey: 'duel_id' });,然后在查询本身中将 as: 'users' 更改为 as: 'players'
      猜你喜欢
      • 2011-07-23
      • 2017-03-19
      • 2013-10-16
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      相关资源
      最近更新 更多