为什么数据出现在 mutation 上,但没有出现在 query 上?
Why the data appears on mutation, but does not appear on query?
我有学生,他们可以选修不同的课程。当我创建一个新学生时,我将课程 ID(数组)作为参数以通过 ID 获取课程信息。我正在将信息传递给学生课程数组。问题是当我 运行 突变时,新创建的学生有课程数据(如下图所示):
但是当我调用学生查询以查看所有学生时,它为新创建数据的课程提供了一个空数组。
我用console.log()检查了行前后的数据-> await newStudent.save();。在调用保存之前它是一个空数组,但在调用它之后课程出现了。这是什么原因?
学生实体:
@ObjectType()
export class Student {
@Field()
readonly _id: ObjectId;
@Field()
@Prop({ required: true })
name: string;
@Field()
@Prop({ required: true, unique: true })
email: string;
@Field()
@Prop({ required: true })
password: string;
@Field()
@Prop({ required: true, unique: true })
facultyNumber: number;
@Field()
@Prop({ default: Date.now() })
lastLogin?: number;
@Field(type => [Course], {nullable: true})
@Prop({default: []})
courses?: Course[]
}
课程实体:
@ObjectType()
export class Course {
@Field()
readonly _id: ObjectId;
@Field()
@Prop({ required: true })
title: string;
@Field()
@Prop({ required: true })
description: string;
@Field()
@Prop({ required: true })
subject: string;
@Field()
@Prop({ required: true })
credits: number;
@Field()
@Prop({ required: true })
tutor: string;
}
export const CourseModel = getModelForClass(Course);
学生解析器:
@Resolver()
export class StudentResolver {
@Query(returns => Student)
async student(@Arg("_id") _id: string): Promise<Student> {
return await StudentModel.findById(_id);
}
@Query(returns => [Student])
async students(): Promise<Student[]> {
return await StudentModel.find({});
}
@Mutation(returns => Student)
async createStudent(@Arg("data") data: StudentInput): Promise<Student> {
const a: CourseResolver = new CourseResolver();
const studentData = { ...data, password: bcryptjs.hashSync(data.password, 5) }
const newStudent = new StudentModel(studentData);
if(newStudent.courses == undefined){
newStudent.courses = [];
}
data.coursesIDs.map((id) => {
a.course(id).then((res) => {
newStudent.courses.push(res);
});
});
console.log("before saving courses", newStudent)
await newStudent.save();
console.log("after saving coures", newStudent)
return newStudent;
}
}
课程解析器:
@Resolver()
export class CourseResolver {
@Query(returns => Course)
async course(@Arg("_id") _id: string): Promise<Course> {
return await CourseModel.findById(_id);
}
}
学生论点:
@InputType({ description: "New student data" })
export class StudentInput {
@Field()
@MaxLength(50)
name: string;
@Field()
@IsEmail()
@MaxLength(30)
email: string;
@Field()
@MinLength(6)
password: string;
@Field()
@IsInt()
@IsPositive()
@Min(1000000000)
facultyNumber: number;
@Field(type => [String], { nullable: true})
coursesIDs?: string[]
}
解法:
await Promise.all(data.coursesIDs.map(async(id) => {
const promise: Promise<Course> = CourseModel.findById(id).then((res) => {
newStudent.courses.push(res);
return res;
});
await Promise.resolve(promise);
}));
您是否检查过您的数据库以查看课程是否与学生相关联?
之所以不是,是因为在您的地图中,您再次执行一个承诺,您应该 return,然后在保存记录之前等待所有这些承诺。
...
const promises = data.coursesIDs.map((id) => {
return a.course(id).then((res) => {
newStudent.courses.push(res);
});
});
await Promise.all(promises)
...
简短版
await Promise.all(data.coursesIDs.map(id => a.course(id).then(newStudent.courses.push)))
查询数据库的时候,还应该populate the relationships.
StudentModel.findById(_id).populate('courses')
和
StudentModel.find({}).populate('courses')
同时检查共享服务的使用情况,您可以将其注入解析器 (Dependency Injection) 并调用这些服务来解析您的课程,而不是在您的变更中创建 CourseResolver 的新实例。
创建一个 'CourseService' 并注入 StudentResolver 和 CourseRolvers。 'CourseService' 应该有一个像 findOneByID 这样的方法,它在模型上或通过存储库调用该方法。
我有学生,他们可以选修不同的课程。当我创建一个新学生时,我将课程 ID(数组)作为参数以通过 ID 获取课程信息。我正在将信息传递给学生课程数组。问题是当我 运行 突变时,新创建的学生有课程数据(如下图所示):
但是当我调用学生查询以查看所有学生时,它为新创建数据的课程提供了一个空数组。
我用console.log()检查了行前后的数据-> await newStudent.save();。在调用保存之前它是一个空数组,但在调用它之后课程出现了。这是什么原因?
学生实体:
@ObjectType()
export class Student {
@Field()
readonly _id: ObjectId;
@Field()
@Prop({ required: true })
name: string;
@Field()
@Prop({ required: true, unique: true })
email: string;
@Field()
@Prop({ required: true })
password: string;
@Field()
@Prop({ required: true, unique: true })
facultyNumber: number;
@Field()
@Prop({ default: Date.now() })
lastLogin?: number;
@Field(type => [Course], {nullable: true})
@Prop({default: []})
courses?: Course[]
}
课程实体:
@ObjectType()
export class Course {
@Field()
readonly _id: ObjectId;
@Field()
@Prop({ required: true })
title: string;
@Field()
@Prop({ required: true })
description: string;
@Field()
@Prop({ required: true })
subject: string;
@Field()
@Prop({ required: true })
credits: number;
@Field()
@Prop({ required: true })
tutor: string;
}
export const CourseModel = getModelForClass(Course);
学生解析器:
@Resolver()
export class StudentResolver {
@Query(returns => Student)
async student(@Arg("_id") _id: string): Promise<Student> {
return await StudentModel.findById(_id);
}
@Query(returns => [Student])
async students(): Promise<Student[]> {
return await StudentModel.find({});
}
@Mutation(returns => Student)
async createStudent(@Arg("data") data: StudentInput): Promise<Student> {
const a: CourseResolver = new CourseResolver();
const studentData = { ...data, password: bcryptjs.hashSync(data.password, 5) }
const newStudent = new StudentModel(studentData);
if(newStudent.courses == undefined){
newStudent.courses = [];
}
data.coursesIDs.map((id) => {
a.course(id).then((res) => {
newStudent.courses.push(res);
});
});
console.log("before saving courses", newStudent)
await newStudent.save();
console.log("after saving coures", newStudent)
return newStudent;
}
}
课程解析器:
@Resolver()
export class CourseResolver {
@Query(returns => Course)
async course(@Arg("_id") _id: string): Promise<Course> {
return await CourseModel.findById(_id);
}
}
学生论点:
@InputType({ description: "New student data" })
export class StudentInput {
@Field()
@MaxLength(50)
name: string;
@Field()
@IsEmail()
@MaxLength(30)
email: string;
@Field()
@MinLength(6)
password: string;
@Field()
@IsInt()
@IsPositive()
@Min(1000000000)
facultyNumber: number;
@Field(type => [String], { nullable: true})
coursesIDs?: string[]
}
解法:
await Promise.all(data.coursesIDs.map(async(id) => {
const promise: Promise<Course> = CourseModel.findById(id).then((res) => {
newStudent.courses.push(res);
return res;
});
await Promise.resolve(promise);
}));
您是否检查过您的数据库以查看课程是否与学生相关联?
之所以不是,是因为在您的地图中,您再次执行一个承诺,您应该 return,然后在保存记录之前等待所有这些承诺。
...
const promises = data.coursesIDs.map((id) => {
return a.course(id).then((res) => {
newStudent.courses.push(res);
});
});
await Promise.all(promises)
...
简短版
await Promise.all(data.coursesIDs.map(id => a.course(id).then(newStudent.courses.push)))
查询数据库的时候,还应该populate the relationships.
StudentModel.findById(_id).populate('courses')
和
StudentModel.find({}).populate('courses')
同时检查共享服务的使用情况,您可以将其注入解析器 (Dependency Injection) 并调用这些服务来解析您的课程,而不是在您的变更中创建 CourseResolver 的新实例。
创建一个 'CourseService' 并注入 StudentResolver 和 CourseRolvers。 'CourseService' 应该有一个像 findOneByID 这样的方法,它在模型上或通过存储库调用该方法。