Search code examples
node.jstypescripttypeormtypegraphql

Usage of ManyToOne relation returns null in TypeGraphQL


For learning, I made a project testing out TypeGraphql, together with TypeORM. I have a User and Book entity, where I want to have a created_by field on the Book entity.

@ObjectType()
@Entity()
export class Book extends BaseEntity {
  @Field(() => ID)
  @PrimaryGeneratedColumn()
  readonly id: number;

  @Field({ nullable: true })
  @Column({ nullable: true })
  name: string;

  @Field(() => User)
  @ManyToOne(() => User)
  @JoinColumn({ name: 'created_by' })
  created_by: User;
  // @RelationId((orthodontist: Orthodontist) => orthodontist.created_by)
  // createdById: number;
}

@ObjectType()
@Entity()
export class User extends BaseEntity {
    @Field(() => ID)
    @PrimaryGeneratedColumn()
    id: number;

    @Field({ nullable: true })
    @Column({ nullable: true })
    first_name?: string;

    @Field({ nullable: true })
    @Column({ nullable: true })
    last_name?: string;

    @Field()
    @Column({ unique: true })
    email: string;

    @Column()
    password: string;

    @Field(() => [Book!])
    @OneToMany(() => Book, book => book.created_by)
    created_books: Book[];

}

For my resolver, it simply looks like this, which I am properly loading as the docs say.

@Resolver(Book)
export class OrthodontistResolver {

    @Query(() => [Book])
    books(): Promise<Book[]> {
        return Book.find();
    }
}

When I go into my GraphQL playground, and query something like this:

{
  books {
    name,
    id,
  }
}

It all works and returns the right data. However, when I try to use the created_by field like this:

{
  orthodontists {
    name,
    id,
    created_by {
      id
    }
  }
}

It gives me the following error:

Cannot return null for non-nullable field Book.created_by.

I made sure the relation exists in the database, and set up correctly with it's FK's. Where does this come from though? How can I fix this? I did try using the @RelationId decorator, as seen in the first code example. It unfortunately didn't work.

EDIT:

There is only one book in the database, where the created_by field is not null.


Solution

  • Change your books resolver to return the relationship created_by when using find operation:

    @Resolver(Book)
    export class OrthodontistResolver {
    
      @Query(() => [Book])
      books(): Promise<Book[]> {
        return Book.find({
          relations: ["created_by"],
        });
      }
    }