我目前正在研究一个项目,让我的玩家以1v1或2v2的概念与对方玩游戏。
所以我创建了以下2个sequelize类:
player.js
export class Player extends Model {
static init(sequelize, DataTypes) {
return super.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
gender: DataTypes.STRING,
firstName: DataTypes.STRING,
lastName: DataTypes.STRING
},
{
sequelize
}
);
}
// Associations
static associate() {
this.games1 = this.hasMany(Game, { as: 'player1_team1', foreignKey: 'player1Team1Id' });
this.games2 = this.hasMany(Game, { as: 'player1_team2', foreignKey: 'player1Team2Id' });
this.games3 = this.hasMany(Game, { as: 'player2_team1', foreignKey: 'player2Team1Id' });
this.games4 = this.hasMany(Game, { as: 'player2_team2', foreignKey: 'player2Team2Id' });
}
}
game.js
export class Game extends Model {
static init(sequelize, DataTypes) {
return super.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
playedAt: DataTypes.DATE,
set1_team1: {
type: DataTypes.INTEGER,
allowNull: true
},
set1_team2: {
type: DataTypes.INTEGER,
allowNull: true
},
set2_team1: {
type: DataTypes.INTEGER,
allowNull: true
},
set2_team2: {
type: DataTypes.INTEGER,
allowNull: true
},
set3_team1: {
type: DataTypes.INTEGER,
allowNull: true
},
set3_team2: {
type: DataTypes.INTEGER,
allowNull: true
}
},
{
sequelize
}
);
}
// Associations
static associate() {
this.player1_team1 = this.belongsTo(Player, {
as: 'player1_team1',
foreignKey: 'player1Team1Id'
});
this.player1_team2 = this.belongsTo(Player, {
as: 'player1_team2',
foreignKey: 'player1Team2Id'
});
this.player2_team1 = this.belongsTo(Player, {
as: 'player2_team1',
foreignKey: 'player2Team1Id'
});
this.player2_team2 = this.belongsTo(Player, {
as: 'player2_team2',
foreignKey: 'player2Team2Id'
});
}
}
然后为GraphQl提供以下方案
gql`
type Player {
id: ID!
firstName: String!
lastName: String!
games: [Game]
}
type Game {
id: ID!
player1_team1: Player!
player1_team2: Player!
player2_team1: Player!
player2_team2: Player!
}
type Query {
player(id: ID!): Player
}
`
现在,当您查询Player
时,无论他是player1_team1,player2_team2 ...,您都可以获取所有游戏。
但是我在确定如何执行此操作时有点受阻:/
我尝试添加getGames()
并将4个数组组合到我的类中,但是我没有找到如何调用该方法的方法
getGames() {
return [...this.games1, ...this.games2, ...this.games3, ...this.games4];
}
我尝试搜索一种方式,该方式可以使用结合了4个子代(player1_team1 ...)的别名进行查询,但是没有成功(在GraphQl中还是新功能)
有人可以帮我吗?
答案 0 :(得分:1)
Game
是类。调用new Game
或类似Game.create
的静态方法将生成该类的 instance 。所以我们有
const Game = require('the location of the model')
const game = new Game()
在此示例中,静态方法将在Game
变量上可用,因为它们适用于该类,而不是该类的实例。同样,您在类中定义的非静态方法将在实例上可用,而不在类(即game
变量)上可用。
hasMany方法在两个模型之间创建关联,并返回HasMany类的实例。通过编写以下内容:
this.games1 = this.hasMany(Game, { ... })
您正在设置games1
静态属性,因为您是在静态方法中进行此操作的。结果,该属性在类而不是实例上可用。将结果关联对象保存为静态属性可能会有所帮助,但也没有必要。您可以轻松地做到这一点:
this.hasMany(Game, { ... })
重要的一点是,通过调用hasMany
,您实际上是在该类的实例上创建一个getter。在这种情况下,将根据您提供的别名(getPlayer1_team1
参数)将这四个getter分别命名为getPlayer2_team1
,getPlayer1_team2
,getPlayer2_team2
和as
。 / p>
因此您可以添加如下方法:
async getGames() {
const [games1, games2, games3, games4] = await Promise.all([
this.getPlayer1_team1(),
this.getPlayer1_team2(),
this.getPlayer2_team1(),
this.getPlayer2_team2(),
])
return [...this.games1, ...this.games2, ...this.games3, ...this.games4]
}
然后从某个实例调用它:
const player = await Player.findByPk(1)
const games = await Player.getGames()
如果您的架构在games
类型上公开了Player
字段,则可以在该字段的解析程序中执行此操作:
function resolve(parent, args, context, info) {
return parent.getGames()
}
或者...
您可以延迟加载关联的模型并在获取玩家时获取游戏。通常,这比先获取玩家然后再获取游戏更有效。因此,在获取播放器时,您可以执行以下操作:
const player = await Player.findByPk(1, {
include: [
{ as: 'player1_team1', model: Game },
{ as: 'player1_team2', model: Game },
{ as: 'player2_team1', model: Game },
{ as: 'player2_team2', model: Game },
]
})
注意:务必包含定义关联时使用的相同的as
值。现在,生成的player
变量将为关联的游戏(player1_team1
,player1_team2
等)具有4个属性。
假设您在获取Player实例时像这样延迟加载了相关的游戏,则现在可以执行类似的操作来解决GraphQL中的games
字段:
function resolve(parent, args, context, info) {
return [
...parent.player1_team1,
...parent.player1_team2,
...parent.player2_team1,
...parent.player2_team2,
]
}