为什么数据出现在 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 这样的方法,它在模型上或通过存储库调用该方法。