【发布时间】:2022-02-13 18:32:03
【问题描述】:
我正在使用 Apollo、Sequelize、Node 和 MySQL 开发 GraphQL 服务器。数据由视频和团队(在这些视频中)组成。我还使用非标准外键将团队连接到特定视频(数据库表 Teams 有一个名为“inVideo”的字段,而不是默认的“VideoId”字段)。创建视频和团队以及查询特定的(带有 id)或所有项目都不是问题。但是,当我尝试查询属于特定视频的团队时(通过提供特定视频的 id),后端的 SQL SELECT 查询包含一个附加字段名称,它是默认的外键构造“VideoId”,并且作为该字段在数据库中不存在,查询失败。
这里是创建 Teams 表的迁移文件(注意 inVideo-field 定义):
'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Teams', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
inVideo: {
allowNull: false,
type: Sequelize.INTEGER
},
name: {
allowNull: false,
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Teams');
}
};
这是Sequelize的团队模型定义(注意belongsTo中的foreignKey定义)
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Team extends Model {
static associate(models) {
Team.belongsTo(models.Video, { foreignKey: "inVideo" })
}
}
Team.init({
name: {
allowNull: false,
type: DataTypes.STRING
}
}, {
sequelize,
modelName: 'Team',
});
return Team;
};
在数据库中生成视频表的迁移文件没有什么特别之处,但这里是视频的Sequelize模型文件(因为我在该模型中添加了hasMany关系):
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Video extends Model {
static associate(models) {
Video.hasMany(models.Team)
}
}
Video.init({
videoUrl: {
allowNull: false,
type: DataTypes.STRING
}
}, {
sequelize,
modelName: 'Video',
});
return Video;
};
然后是 GraphQL 架构定义
const { gql } = require('apollo-server');
const typeDefs = gql`
type Video {
id: Int!
videoUrl: String!
teams: [Team!]!
}
type Team {
id: Int!
name: String!
video: Video!
}
type Query {
teams(inVideo: Int!): [Team!]!
}
type Mutation {
createVideo(videoUrl: String!): Video!
createTeam(inVideo: Int!, name: String!): Team!
}
`;
module.exports = typeDefs;
最后是服务器的解析器定义:
const resolvers = {
Query: {
async teams(root, { inVideo }, { models }) {
return models.Team.findAll({
where: {
inVideo: inVideo
}
});
},
},
Mutation: {
async createVideo(root, { videoUrl }, { models }) {
return models.Video.create({ videoUrl });
},
async createTeam( root, { inVideo, name }, { models }) {
return models.Team.create({ inVideo, name });
},
},
Video: {
async teams(video) {
return video.getTeams();
},
},
Team: {
async video(team) {
return team.getVideo();
},
},
};
module.exports = resolvers;
如上所述,创建视频和团队工作正常,并且数据库中的数据是正确的。但是,当我尝试查询服务器以获取某个视频的团队时,SQL SELECT 子句如下:
SELECT `id`, `name`, `createdAt`, `updatedAt`, `inVideo`, `VideoId` FROM `Teams` AS `Team` WHERE `Team`.`inVideo` = 1;
VideoId字段不应该在那里,因为它在数据库中不存在(关系信息存储在inVideo字段中)。
我怎样才能摆脱这种行为? (我认为 belongsTo 方法调用中的 foreignKey 选项可以解决这个问题)
另外,我使用关系定义关系/查询团队的方式(使用 findAll 的 where-option)可能不正确。有没有更好的方法来做到这一点?
【问题讨论】:
标签: graphql sequelize.js apollo-server