How to create a many-to-many relationship type-graphql typeorm

1.2k Views Asked by At

I'm working on a project using type-graphql and typeorm. I have two entities: Meals and Ingredients, and I wish to create a many to many relationship between these two entities.

I have added the following code in my Meal.ts file:

@Field(() => [Ingredient])
@ManyToMany(() => Ingredient, ingredient => ingredient.meals, { onUpdate: "NO ACTION" })
@JoinTable({ joinColumn: { name: "meal_id" }, inverseJoinColumn: { name: "ingredient_id" } })
ingredients!: Promise<Ingredient[]>

and the following code in my Ingredient.ts file:

@Field(() => [Meal])
@ManyToMany(() => Meal, meal => meal.ingredients, { onUpdate: "NO ACTION" })
meals!: Promise<Meal[]>

Additionally, I have written this code for my migration:

CREATE TABLE "meal_ingredient" (
  "id" uuid NOT NULL DEFAULT uuid_generate_v4() PRIMARY KEY,
  "meal_id" uuid NOT NULL,
  "ingredient_id" uuid NOT NULL,
  FOREIGN KEY ("meal_id") REFERENCES "meal"("id") ON DELETE CASCADE ON UPDATE NO ACTION,
  FOREIGN KEY ("ingredient_id") REFERENCES "ingredient"("id") ON DELETE CASCADE ON UPDATE NO ACTION
)

I think this sufficiently establishes the relationship I want between the two entities (although if I'm wrong please let me know). What I'm wondering is, what do I have to add to my Resolver files in order to be able to link a meal and an ingredient? Meaning that, if I have a given meal and ingredient, how, in my resolver, can I define a mutation to create a row in the meal_ingredient table so that I can later query the meal's ingredient or the ingredient's meal.

1

There are 1 best solutions below

2
On

You need a FieldResolver (docs) to query relational data, either in a one-to-many or many-to-many relationship:

@Resolver(() => Ingredient)
class IngredientResolver {
  // your other query and mutations

  @FieldResolver(() => Meal)
  async getMeal(@Root() meal: Meal): Promise<Meal | undefined> { 
    // Root is equivalent to parent in graphql
    return Meal.findOne(meal.id) // use this syntax if your Entity extends BaseEntity 
  }
}

Note that, this will cause the typical n+1 problem with graphql, meaning when you fetch an array of Ingredients, and with every ingredient that includes Meal, graphql has to perform db querying for the meals that belong to each ingredient, the solution to n + 1 problem is to use dataloader that batches the data requests