-1

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);
    }
}
Enchantres
  • 853
  • 2
  • 9
  • 22
  • 2
    Does this answer your question? [How to access the value of a promise?](https://stackoverflow.com/questions/29516390/how-to-access-the-value-of-a-promise) – Quentin May 21 '22 at 18:54
  • No. I have tried the following statement: return a.course(id).then((res) => {return res});, but there is still an error on this line. – Enchantres May 21 '22 at 19:01
  • 1
    `.then()` still returns a promise – VLAZ May 21 '22 at 19:04

1 Answers1

0

I solved it by using then() and pushing the response I get from the Promise to the courses array.

@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);
        data.coursesIDs.map((id) => {
            a.course(id).then((res) => {
                newStudent.courses.push(res);
            });
        });
        await newStudent.save();
        return newStudent;
    }
Enchantres
  • 853
  • 2
  • 9
  • 22