I want to create a many-to-many relationship between two objects - courses and students. I use MongoDB. When creating a new student I want to be able to add the courses. In createStudent mutation I am calling the query for getting the course which I defined in Course Resolver, but the following error occurs:
Type 'Promise[]' is not assignable to type 'Course[]'. Type 'Promise' is missing the following properties from type 'Course': _id, title, description, subject, and 3 more.
When creating a new student, I want to pass the courses id as a string array. Then in the mutation method I would like to map these ids to the Course objects from the database and return an array of courses which I want to pass to the student data. How can I do this?
Here is the student entity:
@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])
@ManyToMany(() => Course, course => course._id, { cascade: true })
@JoinTable({ name: "student_courses",joinColumn: { name: "student_id" }, inverseJoinColumn: { name: "course_id" } })
@Prop({default: []})
courses?: Course[]
}
export const StudentModel = getModelForClass(Student, { schemaOptions: { timestamps: true } });
Courses entity:
@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;
@Field(() => [Student])
@ManyToMany(() => Student, student => student._id, { cascade: true})
students!: Student[]
}
export const CourseModel = getModelForClass(Course);
The input arguments for student creation:
@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[]
}
Student resolver:
@Resolver()
export class StudentResolver {
@Mutation(returns => Student)
async createStudent(@Arg("data") data: StudentInput): Promise<Student> {
const a: CourseResolver = new CourseResolver();
const courses: Course[] = data.coursesIDs.map((id) => {
return Promise.resolve(a.course(id));
});
const studentData = { ...data, password: bcryptjs.hashSync(data.password, 5) }
const newStudent = new StudentModel(studentData);
newStudent.courses = courses;
await newStudent.save();
return newStudent;
}
}
Course resolver:
@Resolver()
export class CourseResolver {
@Query(returns => Course)
async course(@Arg("_id") _id: string): Promise<Course> {
return await CourseModel.findById(_id);
}
}