Coookbooks

Explore ingredients

Not only can you use simple queries to explore our ingredients database. It is possible to search for specific ingredients, i.e. containing a desired string.

Search ingredients

query search_ingredients{
  ingredients(searchName: "appl"){
    id
    name
  }
}
{
    "data": {
        "ingredients": [
            {
                "id": "7",
                "name": "apple"
            },
            {
                "id": "9",
                "name": "apple cider vinegar"
            },
            {
                "id": "391",
                "name": "apple cider"
            },
            {
                "id": "392",
                "name": "apple juice"
            },
            {
                "id": "660",
                "name": "applesauce"
            },
            {
                "id": "233",
                "name": "pineapple"
            },
            {
                "id": "441",
                "name": "pineapple juice"
            }
        ]
    }
}

The search works also in multiple languages. Target language can be defined using QueryMeta.

query search_ingredients{
  ingredients(
    searchName: "apf"
    meta: {language: de}
  ){
    id
    name
  }
}
{
  "data": {
    "ingredients": [
      {
        "id": "7",
        "name": "Apfel"
      },
      {
        "id": "9",
        "name": "Apfelessig"
      },
      {
        "id": "391",
        "name": "Apfelwein"
      },
      {
        "id": "392",
        "name": "Apfelsaft"
      },
      {
        "id": "240",
        "name": "Granatapfel"
      },
      {
        "id": "442",
        "name": "Granatapfelsaft"
      }
    ]
  }
}

Search by tags

In Studio we introduced a versatile concept of Tag. They can be applied for many different objects but let’s have a look how to use them with ingredients. First, we can look up all of the tags within category diet.

query tags{
    tags(category: "diet"){
        id
        name
        category
    }
}
{
    "data": {
        "tags": [
            {
                "id": "129",
                "name": "protein",
                "category": "diet"
            },
            {
                "id": "130",
                "name": "gut_health",
                "category": "diet"
            },
            {
                "id": "131",
                "name": "energy",
                "category": "diet"
            },
            {
                "id": "132",
                "name": "immune",
                "category": "diet"
            }
        ]
    }
}

For tag-based filtering we can use on of two methods: * tagAnd * tagOr

The former returns objects containing all of the tags, whereas the latter, objects containing at least one tag.

query ingredient_matches {
  ingredients(tagsAnd: [130,132]){
      id
      name
    }
  }
{
    "data": {
        "ingredients": [
            {
                "id": "2",
                "name": "agave nectar"
            },
            {
                "id": "3",
                "name": "allspice"
            },
            {
                "id": "4",
                "name": "almonds"
            },
            {
                "id": "6",
                "name": "aniseed"
            },
            {
                "id": "12",
                "name": "artichoke"
            }
        ]
    }
}

Foodpairing suggestions

Getting foodpairing suggestions for a set of ingredients allows to discover sets of ingredients that go well together. It can be looked up using matchScore.

query ingredient_matches {
  ingredients(matchTo: [17,59,420]){
    id
    name
    matchScore
  }
}
{
    "data": {
        "ingredients": [
            {
                "id": "1",
                "name": "acorn squash",
                "matchScore": 0.0004640691881603378
            },
            {
                "id": "2",
                "name": "agave nectar",
                "matchScore": 0.02274141704122339
            },
            {
                "id": "3",
                "name": "allspice",
                "matchScore": 0.00022409417768347553
            },
            {
                "id": "4",
                "name": "almonds",
                "matchScore": 0.0021007983922955156
            },
            {
                "id": "5",
                "name": "almond milk",
                "matchScore": 0.0036235160235011466
            },
            {
                "id": "6",
                "name": "aniseed",
                "matchScore": 7.615664095746823e-05
            },
            {
                "id": "7",
                "name": "apple",
                "matchScore": 0.00236664036616851
            }
          ]
        }
      }

To get most out of the foodparing, let’s order results by matchSchore using :ref:DjangoFilterInput. Using pagination we can limit the ordered output to 5 best matching ingredients.

query ingredient_matches {
  ingredients(
    matchTo: [17,59,420], djangoFilter: {orderBy: "-match_score"}, pagination: {limitTo: 5}){
    id
    name
    matchScore
  }
}
{
    "data": {
        "ingredients": [
            {
                "id": "424",
                "name": "ice",
                "matchScore": 0.09933129980019301
            },
            {
                "id": "425",
                "name": "lemon juice",
                "matchScore": 0.07360623298953682
            },
            {
                "id": "126",
                "name": "ginger",
                "matchScore": 0.04576136137822641
            },
            {
                "id": "563",
                "name": "ground ginger",
                "matchScore": 0.04576136137822641
            },
            {
                "id": "22",
                "name": "banana",
                "matchScore": 0.03861570815494316
            }
        ]
    }
}

How to get a recipe?

Find a dish

First, let’s find out what dishes there are in studio.

query dishes {
  dishes {
    name
    description
  }
}
{
  "data": {
    "dishes": [
      {
        "id": "91",
        "name": "Burrito",
        "description": "Burritos are Tex-Mex traditions - but you can put ANYTHING in them!",
        "estimatedPreparationTime": 20,
        "recipeNote": "Don't shy away from adding too many spices and herbs, Mexican cuisine is always spiced!"
      },
      {
          "id": "241",
          "name": "Christmas Roasted Veggies",
          "description": "Create your own roasted veggies for Christmas that can stand alone as a dish or act as the perfect side.",
          "estimatedPreparationTime": 40,
          "recipeNote": "Let the oven do the work for you!"
      },
      {
          "id": "173",
          "name": "Eggplant Pizza",
          "description": "Create your very own eggplant pizza and our AI will help you match the rest of the ingredients together.",
          "estimatedPreparationTime": 30,
          "recipeNote": "Don't worry if you can't finish your pizza, it will be a perfect snack for lunch the next day!"
      }
    ]
}

Generate a recipe

If we decide which Dish to pick, we can generate a recipe. A recipe consists of different standalone modules: Blueprint and Volume.

query getRecipe {
  dishes(id: 24) {
    name
    serving {
      name
      amount
    }
    ratio {
      volumes(ingredients: [28,55,206,167,271]) {
        ingredient {
          id
          name
        }
        grams
        unitCount
        unit {
          name
        }
      }
    }
    blueprint {
      instructions(ingredients: [28,55,206,167,271]) {
        text
        method
        ingredients {
          id
          name
          }
        }
      }
    }
  }
{
  "data": {
      "dishes": [
          {
              "name": "Ovenroasted Mediterranean Veggies",
              "serving": {
                  "name": "Portions",
                  "amount": 1.0
              },
              "ratio": {
                  "volumes": [
                      {
                          "ingredient": {
                              "id": "28",
                              "name": "beets"
                          },
                          "grams": 180,
                          "unitCount": 180.0,
                          "unit": {
                              "name": "grams"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "55",
                              "name": "carrot"
                          },
                          "grams": 120,
                          "unitCount": 2.0,
                          "unit": {
                              "name": "pieces"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "167",
                              "name": "lemon"
                          },
                          "grams": 15,
                          "unitCount": 1.0,
                          "unit": {
                              "name": "tbsp"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "206",
                              "name": "olive oil"
                          },
                          "grams": 20,
                          "unitCount": 25.0,
                          "unit": {
                              "name": "ml"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "271",
                              "name": "rosemary"
                          },
                          "grams": 2,
                          "unitCount": 0.5,
                          "unit": {
                              "name": "tsp"
                          }
                      }
                  ]
              },
              "blueprint": {
                  "instructions": [
                      {
                          "text": "Preheat your oven to 200°C (400°F).",
                          "method": null,
                          "ingredients": []
                      },
                      {
                          "text": "Peel and cut the beets and carrot.",
                          "method": "prep",
                          "ingredients": [
                              {
                                  "id": "28",
                                  "name": "beets"
                              },
                              {
                                  "id": "55",
                                  "name": "carrot"
                              }
                          ]
                      },
                      {
                          "text": "Cut and squeeze the juice from the lemon.",
                          "method": "prep",
                          "ingredients": [
                              {
                                  "id": "167",
                                  "name": "lemon"
                              }
                          ]
                      },
                      {
                          "text": "Spread the beets evenly on a pan with rosemary and toss with olive oil. Roast at 175°C for 15 minutes. Add carrot and roast for another 30 minutes or until tender.",
                          "method": "roast",
                          "ingredients": [
                              {
                                  "id": "28",
                                  "name": "beets"
                              },
                              {
                                  "id": "55",
                                  "name": "carrot"
                              },
                              {
                                  "id": "206",
                                  "name": "olive oil"
                              },
                              {
                                  "id": "271",
                                  "name": "rosemary"
                              }
                          ]
                      },
                      {
                          "text": "Add salt and pepper to taste.",
                          "method": null,
                          "ingredients": []
                      },
                      {
                          "text": "Mix the lemon with a little oil or water.Then drizzle it on top.",
                          "method": "dressing",
                          "ingredients": [
                              {
                                  "id": "167",
                                  "name": "lemon"
                              }
                          ]
                      }
                  ]
              }
          }
      ]
  }
}

Change recipe language, UnitsSystem and portions

A recipe can be manipulated in many different ways. For instance, it can be presented in a different language using Language, use different set of units by specifying a units system or generate volumes for multiple portions.

query getRecipe {
    dishes(id: 24, meta: {language: da, unitsSystem: IMPERIAL}) {
      name
      serving {
        name
        amount
      }
      ratio {
        volumes(ingredients: [28,55,206,167,271], portions: 3) {
          ingredient {
            id
            name
          }
          grams
          unitCount
          unit {
            name
          }
        }
      }
      blueprint {
        instructions(ingredients: [28,55,206,167,271]) {
          text
          method
          ingredients {
            id
            name
          }
        }
      }
    }
  }
{
  "data": {
      "dishes": [
          {
              "name": "Ovnbagte Middelhavs-grøntsager",
              "serving": {
                  "name": "Portions",
                  "amount": 1.0
              },
              "ratio": {
                  "volumes": [
                      {
                          "ingredient": {
                              "id": "28",
                              "name": "rødbede"
                          },
                          "grams": 530,
                          "unitCount": 4.0,
                          "unit": {
                              "name": "kop"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "55",
                              "name": "gulerod"
                          },
                          "grams": 360,
                          "unitCount": 6.0,
                          "unit": {
                              "name": "stykker"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "167",
                              "name": "citron"
                          },
                          "grams": 40,
                          "unitCount": 3.0,
                          "unit": {
                              "name": "spsk."
                          }
                      },
                      {
                          "ingredient": {
                              "id": "206",
                              "name": "olivenolie"
                          },
                          "grams": 60,
                          "unitCount": 0.25,
                          "unit": {
                              "name": "kop"
                          }
                      },
                      {
                          "ingredient": {
                              "id": "271",
                              "name": "rosmarin"
                          },
                          "grams": 6,
                          "unitCount": 0.5,
                          "unit": {
                              "name": "spsk."
                          }
                      }
                  ]
              },
              "blueprint": {
                  "instructions": [
                      {
                          "text": "Tænd ovnen på 200°C.",
                          "method": null,
                          "ingredients": []
                      },
                      {
                          "text": "Skræl og skær beets and carrot.",
                          "method": "prep",
                          "ingredients": [
                              {
                                  "id": "28",
                                  "name": "rødbede"
                              },
                              {
                                  "id": "55",
                                  "name": "gulerod"
                              }
                          ]
                      },
                      {
                          "text": "Skær og pres saften fra  lemon.",
                          "method": "prep",
                          "ingredients": [
                              {
                                  "id": "167",
                                  "name": "citron"
                              }
                          ]
                      },
                      {
                          "text": "Spred beets ud på en pande. med rosmarin og tilføj olive oil. Ovnsteg ved 175°C i 15 minutter. Tilføj carrot og ovnsteg igen for 30 minutter eller indtil mørt.",
                          "method": "roast",
                          "ingredients": [
                              {
                                  "id": "28",
                                  "name": "rødbede"
                              },
                              {
                                  "id": "55",
                                  "name": "gulerod"
                              },
                              {
                                  "id": "206",
                                  "name": "olivenolie"
                              },
                              {
                                  "id": "271",
                                  "name": "rosmarin"
                              }
                          ]
                      },
                      {
                          "text": "Smag til med salt og peber.",
                          "method": null,
                          "ingredients": []
                      },
                      {
                          "text": "Bland citron med lidt olie eller vand.Fordel det derefter ovenpå.",
                          "method": "dressing",
                          "ingredients": [
                              {
                                  "id": "167",
                                  "name": "citron"
                              }
                          ]
                      }
                  ]
              }
          }
      ]
  }
}

Ask for substitutions in a dish

We can check for substitutions of selected ingredients.

query getRecipe {
  dishes(id: 24) {
    name
    sub1: substituteIngredient(targetIngredient: 28, contextIngredients: [55,206,167,271]){
        id
        name
    }
    sub2: substituteIngredient(targetIngredient: 206, contextIngredients: [28,55,167,271]){
        id
        name
    }
  }
}
{
"data": {
    "dishes": [
        {
            "name": "Ovenroasted Mediterranean Veggies",
            "sub1": [
                {
                    "id": "311",
                    "name": "sweet potato"
                },
                {
                    "id": "501",
                    "name": "parsley root"
                },
                {
                    "id": "217",
                    "name": "parsnips"
                }
            ],
            "sub2": [
                {
                    "id": "85",
                    "name": "coconut oil"
                },
                {
                    "id": "333",
                    "name": "vegetable oil"
                },
                {
                    "id": "51",
                    "name": "canola oil"
                },
                {
                    "id": "134",
                    "name": "grapeseed oil"
                }
            ]
        }
    ]
}
}

Balancer

The ingredients are what you have in a recipe. Section of taste SWEET says what can I do if my recipe ended up too sweet. selected is what ingredients counter act the sweetness from the ingredients you have and suggested tells you what else could you add that goes well with your ingredients and also counter acts the sweetness. counterTastes tells you what tastes will help balance the sweetness out.

query balancer {
  balancer(ingredients: [28,55,206,167,271]){
    section(taste: SWEET){
      taste
      selected{
        id
        name
      }
      suggested{
        id
        name
      }
      counterTastes
    }
  }
  }
{
    "data": {
        "balancer": {
            "section": {
                "taste": "SWEET",
                "selected": [
                    {
                        "id": "167",
                        "name": "lemon"
                    },
                    {
                        "id": "271",
                        "name": "rosemary"
                    }
                ],
                "suggested": [
                    {
                        "id": "6",
                        "name": "aniseed"
                    },
                    {
                        "id": "9",
                        "name": "apple cider vinegar"
                    },
                    {
                        "id": "14",
                        "name": "arugula"
                    },
                    {
                        "id": "20",
                        "name": "balsamic vinegar"
                    }
                ],
                "counterTastes": [
                    "SOUR",
                    "SPICY",
                    "BITTER"
                ]
            }
        }
    }
}

Recipe

A functional Type

The Recipe can practically be considered a function, or a recipe generator. Given a dish and a set of ingredients, it returns a complete recipe. Being a functional type, recipes don’t have IDs and are not attached to any database model. They are an abstraction of multiple other Types that generally do have models. These are a few example use cases.

  • Retrieve all data returned, to create the initial recipe

  • Refresh the recipe based on substituted ingredient

  • Refresh amount of portions

variables: {
  "dish": 597,
  "ingredients": [97, 130, 583, 9, 74, 169, 46, 110, 208, 51, 52, 244, 383]
}
query recipe($dish: ID!, $ingredients: [ID]!){
  recipe(dish: $dish, ingredients: $ingredients){
    name
    description
    serving{
      amount
    }
    image{url}
    dish{
      name
    }
    instructions{
      text
    }
    volumes{
      grams
      ingredient{id}
    }
    substitutions{
      originalIngredient{name}
      ingredients{name}
    }
  }
}

The returned data is a recipe that we can display to a user, and they will have all the information they need to give it a spin!

{
  "data": {
    "recipe": {
      "name": "Open-faced Sandwich with Potato",
      "description": "GRIM and Wasa collaboration recipe",
      "serving": {
        "amount": 1
      },
      "image": {
        "url": "https://pjstudio-backend-production.s3-eu-central-1.amazonaws.com/images/kartoffelmad.jpg"
      },
      "dish": {
        "name": "Open-faced Sandwich with Potato"
      },
      "instructions": [
        {
          "text": "Prepare the sauce one day in advance so it has time to cool:"
        },
        {
          "text": "Roughly grate the gouda cheese."
        },
        {
          "text": "Mix the apple cider vinegar, eggs, gouda cheese and lemon zest in a blender."
        },
        {
          "text": "Heat up the cream to a simmer and pour into the blender while running on medium speed. Then turn up to high speed until the mixture is homogenous."
        },
        {
          "text": "Pour the canola oil in a thin stream into the blender while blending. Continue blending until the sauce has a smooth consistency."
        },
        {
          "text": "Cool down the sauce - it will thicken as it cools."
        },
        {
          "text": "Before serving:"
        },
        {
          "text": "Boil the potato."
        },
        {
          "text": "Thinly slice the onion."
        },
        {
          "text": "Coat with white flour."
        },
        {
          "text": "Fry the canola oil and onion and place on a paper towel to drip off."
        },
        {
          "text": "Fry off the butter and capers for a few minutes on medium heat to soften and round the flavor."
        },
        {
          "text": "Add a generous layer of cheese sauce to the crispbread."
        },
        {
          "text": "Slice the potato and add on top."
        },
        {
          "text": "Top with capers, chives and onion."
        }
      ],
      "volumes": [
        {
          "grams": 5,
          "ingredient": {
            "id": "9"
          }
        },
        {
          "grams": 5,
          "ingredient": {
            "id": "46"
          }
        },
        {
          "grams": 25,
          "ingredient": {
            "id": "51"
          }
        },
        {
          "grams": 10,
          "ingredient": {
            "id": "52"
          }
        },
        {
          "grams": 5,
          "ingredient": {
            "id": "74"
          }
        },
        {
          "grams": 25,
          "ingredient": {
            "id": "97"
          }
        },
        {
          "grams": 60,
          "ingredient": {
            "id": "110"
          }
        },
        {
          "grams": 25,
          "ingredient": {
            "id": "130"
          }
        },
        {
          "grams": 2,
          "ingredient": {
            "id": "169"
          }
        },
        {
          "grams": 30,
          "ingredient": {
            "id": "208"
          }
        },
        {
          "grams": 60,
          "ingredient": {
            "id": "244"
          }
        },
        {
          "grams": 10,
          "ingredient": {
            "id": "383"
          }
        },
        {
          "grams": 15,
          "ingredient": {
            "id": "583"
          }
        }
      ],
      "substitutions": [
        {
          "originalIngredient": {
            "id": "9",
            "name": "apple cider vinegar"
          },
          "ingredients": [
            {
              "id": "167",
              "name": "lemon"
            },
            {
              "id": "169",
              "name": "lemon zest"
            },
            {
              "id": "174",
              "name": "lime"
            },
            {
              "id": "175",
              "name": "lime zest"
            },
            {
              "id": "210",
              "name": "orange zest"
            },
            {
              "id": "336",
              "name": "vinegar"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "46",
            "name": "butter"
          },
          "ingredients": [
            {
              "id": "51",
              "name": "canola oil"
            },
            {
              "id": "91",
              "name": "corn oil"
            },
            {
              "id": "134",
              "name": "grapeseed oil"
            },
            {
              "id": "206",
              "name": "olive oil"
            },
            {
              "id": "308",
              "name": "sunflower oil"
            },
            {
              "id": "333",
              "name": "vegetable oil"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "51",
            "name": "canola oil"
          },
          "ingredients": [
            {
              "id": "46",
              "name": "butter"
            },
            {
              "id": "91",
              "name": "corn oil"
            },
            {
              "id": "134",
              "name": "grapeseed oil"
            },
            {
              "id": "308",
              "name": "sunflower oil"
            },
            {
              "id": "333",
              "name": "vegetable oil"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "74",
            "name": "chives"
          },
          "ingredients": [
            {
              "id": "107",
              "name": "dill"
            },
            {
              "id": "216",
              "name": "parsley"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "97",
            "name": "cream"
          },
          "ingredients": [
            {
              "id": "208",
              "name": "onion"
            },
            {
              "id": "229",
              "name": "black pepper"
            },
            {
              "id": "244",
              "name": "potato"
            },
            {
              "id": "279",
              "name": "salt"
            },
            {
              "id": "383",
              "name": "white flour"
            },
            {
              "id": "531",
              "name": "soy cream"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "110",
            "name": "eggs"
          },
          "ingredients": [
            {
              "id": "525",
              "name": "egg substitute"
            },
            {
              "id": "670",
              "name": "aquafaba"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "130",
            "name": "gouda cheese"
          },
          "ingredients": [
            {
              "id": "120",
              "name": "fontina cheese"
            },
            {
              "id": "142",
              "name": "gruyere cheese"
            },
            {
              "id": "494",
              "name": "vegan cheese"
            },
            {
              "id": "517",
              "name": "Muenster cheese"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "169",
            "name": "lemon zest"
          },
          "ingredients": [
            {
              "id": "9",
              "name": "apple cider vinegar"
            },
            {
              "id": "175",
              "name": "lime zest"
            },
            {
              "id": "210",
              "name": "orange zest"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "208",
            "name": "onion"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            },
            {
              "id": "261",
              "name": "red onion"
            },
            {
              "id": "284",
              "name": "shallots"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "244",
            "name": "potato"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "383",
            "name": "white flour"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            },
            {
              "id": "578",
              "name": "gluten-free flour"
            }
          ]
        }
      ]
    }
  }
}

Refresh the recipe

With all the recipe data generated, we might want to adapt the recipe by substituting an ingredient. In this case we are substituting the gouda cheese of id 120 with vegan cheese of id 494

variables: {
  "dish": 597,
  "ingredients": [97, 130, 583, 9, 74, 169, 46, 110, 208, 51, 52, 244, 383]
  "ingredients_substituted": [97, 494, 583, 9, 74, 169, 46, 110, 208, 46, 52, 244, 383]
}
query refreshRecipe($dish: ID!, $ingredients_substituted: [ID]!){
  recipe(dish: $dish, ingredients: $ingredients_substituted){
    instructions{text}
    volumes{
      grams
      ingredient{id}
    }
    substitutions{
      originalIngredient{id}
      ingredients{id}
    }
  }
}

In the response everything has been updated accordingly to our substituted ingredient.

{
  "data": {
    "recipe": {
      "instructions": [
        {
          "text": "Prepare the sauce one day in advance so it has time to cool:"
        },
        {
          "text": "Roughly grate the vegan cheese."
        },
        {
          "text": "Mix the apple cider vinegar, eggs, lemon zest and vegan cheese in a blender."
        },
        {
          "text": "Heat up the cream to a simmer and pour into the blender while running on medium speed. Then turn up to high speed until the mixture is homogenous."
        },
        {
          "text": "Cool down the sauce - it will thicken as it cools."
        },
        {
          "text": "Before serving:"
        },
        {
          "text": "Boil the potato."
        },
        {
          "text": "Thinly slice the onion."
        },
        {
          "text": "Coat with white flour."
        },
        {
          "text": "Fry the onion and place on a paper towel to drip off."
        },
        {
          "text": "Fry off the butter and capers for a few minutes on medium heat to soften and round the flavor."
        },
        {
          "text": "Add a generous layer of cheese sauce to the crispbread."
        },
        {
          "text": "Slice the potato and add on top."
        },
        {
          "text": "Top with capers, chives and onion."
        }
      ],
      "volumes": [
        {
          "grams": 5,
          "ingredient": {
            "id": "9"
          }
        },
        {
          "grams": 5,
          "ingredient": {
            "id": "46"
          }
        },
        {
          "grams": 10,
          "ingredient": {
            "id": "52"
          }
        },
        {
          "grams": 5,
          "ingredient": {
            "id": "74"
          }
        },
        {
          "grams": 30,
          "ingredient": {
            "id": "97"
          }
        },
        {
          "grams": 60,
          "ingredient": {
            "id": "110"
          }
        },
        {
          "grams": 2,
          "ingredient": {
            "id": "169"
          }
        },
        {
          "grams": 30,
          "ingredient": {
            "id": "208"
          }
        },
        {
          "grams": 70,
          "ingredient": {
            "id": "244"
          }
        },
        {
          "grams": 10,
          "ingredient": {
            "id": "383"
          }
        },
        {
          "grams": 30,
          "ingredient": {
            "id": "494"
          }
        },
        {
          "grams": 15,
          "ingredient": {
            "id": "583"
          }
        }
      ],
      "substitutions": [
        {
          "originalIngredient": {
            "id": "9",
            "name": "apple cider vinegar"
          },
          "ingredients": [
            {
              "id": "167",
              "name": "lemon"
            },
            {
              "id": "169",
              "name": "lemon zest"
            },
            {
              "id": "174",
              "name": "lime"
            },
            {
              "id": "175",
              "name": "lime zest"
            },
            {
              "id": "210",
              "name": "orange zest"
            },
            {
              "id": "336",
              "name": "vinegar"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "46",
            "name": "butter"
          },
          "ingredients": [
            {
              "id": "51",
              "name": "canola oil"
            },
            {
              "id": "91",
              "name": "corn oil"
            },
            {
              "id": "134",
              "name": "grapeseed oil"
            },
            {
              "id": "206",
              "name": "olive oil"
            },
            {
              "id": "308",
              "name": "sunflower oil"
            },
            {
              "id": "333",
              "name": "vegetable oil"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "74",
            "name": "chives"
          },
          "ingredients": [
            {
              "id": "107",
              "name": "dill"
            },
            {
              "id": "216",
              "name": "parsley"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "97",
            "name": "cream"
          },
          "ingredients": [
            {
              "id": "208",
              "name": "onion"
            },
            {
              "id": "229",
              "name": "black pepper"
            },
            {
              "id": "244",
              "name": "potato"
            },
            {
              "id": "279",
              "name": "salt"
            },
            {
              "id": "383",
              "name": "white flour"
            },
            {
              "id": "531",
              "name": "soy cream"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "110",
            "name": "eggs"
          },
          "ingredients": [
            {
              "id": "525",
              "name": "egg substitute"
            },
            {
              "id": "670",
              "name": "aquafaba"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "169",
            "name": "lemon zest"
          },
          "ingredients": [
            {
              "id": "9",
              "name": "apple cider vinegar"
            },
            {
              "id": "175",
              "name": "lime zest"
            },
            {
              "id": "210",
              "name": "orange zest"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "208",
            "name": "onion"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            },
            {
              "id": "261",
              "name": "red onion"
            },
            {
              "id": "284",
              "name": "shallots"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "244",
            "name": "potato"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "383",
            "name": "white flour"
          },
          "ingredients": [
            {
              "id": "97",
              "name": "cream"
            },
            {
              "id": "578",
              "name": "gluten-free flour"
            }
          ]
        },
        {
          "originalIngredient": {
            "id": "494",
            "name": "vegan cheese"
          },
          "ingredients": [
            {
              "id": "120",
              "name": "fontina cheese"
            },
            {
              "id": "130",
              "name": "gouda cheese"
            },
            {
              "id": "142",
              "name": "gruyere cheese"
            },
            {
              "id": "517",
              "name": "Muenster cheese"
            }
          ]
        }
      ]
    }
  }
}

Now we have a recipe where we can substitute ingredients, and refresh the content. We might want an additional refresh query, that specifically changes the amount of portions. What we need to update in this instance, are the volumes.

variables: {
  "dish": 597,
  "ingredients": [97, 130, 583, 9, 74, 169, 46, 110, 208, 51, 52, 244, 383],
  "ingredients_substituted": [97, 494, 583, 9, 74, 169, 46, 110, 208, 46, 52, 244, 383],
  "portions": 4
}
query refreshPortions($dish: ID, $ingredients_substituted: [ID], $portions: Int){
  recipe(dish: $dish, ingredients: $ingredients_substituted){
    volumes(portions: $portions){
      grams
      ingredient{id}
    }
  }
}

And in the response we see the IDs of ingredients, and their new measurements in grams, based on 4 portions.

{
  "data": {
    "recipe": {
      "volumes": [
        {
          "grams": 20,
          "ingredient": {
            "id": "9"
          }
        },
        {
          "grams": 20,
          "ingredient": {
            "id": "46"
          }
        },
        {
          "grams": 40,
          "ingredient": {
            "id": "52"
          }
        },
        {
          "grams": 20,
          "ingredient": {
            "id": "74"
          }
        },
        {
          "grams": 120,
          "ingredient": {
            "id": "97"
          }
        },
        {
          "grams": 240,
          "ingredient": {
            "id": "110"
          }
        },
        {
          "grams": 8,
          "ingredient": {
            "id": "169"
          }
        },
        {
          "grams": 130,
          "ingredient": {
            "id": "208"
          }
        },
        {
          "grams": 280,
          "ingredient": {
            "id": "244"
          }
        },
        {
          "grams": 40,
          "ingredient": {
            "id": "383"
          }
        },
        {
          "grams": 120,
          "ingredient": {
            "id": "494"
          }
        },
        {
          "grams": 60,
          "ingredient": {
            "id": "583"
          }
        }
      ]
    }
  }
}

These were a few examples of how you can approach using the Recipe Type.

Tags

Mild Introduction

The Tag is quite universal and powerful for both simple and more advanced filtering. The most important attributes are category and name. One common category is dietary which includes tag names like vegan, nutfree, lactosefree etc.

Tag filtering

In this example, the task is to figure out which diets you can apply with a dish, and given a set of ingredients. Then, create a recipe based on some suggestions that fit the dietary requirements.

Here is our starting point:

variables: {
  "dish": 171,
  "ingredients": [17, 22, 163, 97, 43],
  "category": "dietary"
}
query info($dish: ID, $ingredients: [ID]){
  dishes(id: $dish){
    id
    name
  }
  ingredients(ids: $ingredients){
    id
    name
  }
}
{
  "data": {
    "dishes": [
      {
        "id": "171",
        "name": "Avocado Banana Kiwi Smoothie"
      }
    ],
    "ingredients": [
      {
        "id": "17",
        "name": "avocado"
      },
      {
        "id": "22",
        "name": "banana"
      },
      {
        "id": "43",
        "name": "brown sugar"
      },
      {
        "id": "97",
        "name": "cream"
      },
      {
        "id": "163",
        "name": "kiwi"
      }
    ]
  }
}

As a first step, with the current ingredients we have, it might be a good idea to get a sense of which dietary requirements they already meet. This could easily be its own query, as it is very fast, but in this case we would also like to know which diets are possible with our dish

query dietInfo($dish: ID, $ingredients: [ID], $category: String){
  tags(shared: {type: INGREDIENT, ids: $ingredients}, category: $category){
    id
    name
  }
  dishes(id: $dish){
    id
    name
    adaptableToTags(category: $category){
      id
      name
    }
  }
}

Now we know that with the current ingredients, we are meeting four dietary requirements. However, given the dish, we can see there are more possibilities.

{
  "data": {
    "tags": [
      {
        "id": "16",
        "name": "glutenfree"
      },
      {
        "id": "18",
        "name": "No meat"
      },
      {
        "id": "21",
        "name": "nutfree"
      },
      {
        "id": "247",
        "name": "eggfree"
      }
    ],
    "dishes": [
      {
        "id": "171",
        "name": "Avocado Banana Kiwi Smoothie",
        "adaptableToTags": [
          {
            "id": "16",
            "name": "glutenfree"
          },
          {
            "id": "18",
            "name": "No meat"
          },
          {
            "id": "19",
            "name": "lactosefree"
          },
          {
            "id": "20",
            "name": "diabetic"
          },
          {
            "id": "21",
            "name": "nutfree"
          },
          {
            "id": "17",
            "name": "vegan"
          },
          {
            "id": "247",
            "name": "eggfree"
          }
        ]
      }
    ]
  }
}

Now we will try and get some ingredient suggestions for meeting the vegan dietary requirement. We already know that tag has an id of 17, so we will use that in the query.

query suggestIngredients($dish: ID, $ingredients: [ID]){
  dishes(id: $dish){
    id
    name
    suggestedIngredients(mode: ALL, contextIngredients: $ingredients, adaptToTags: [17]){
      id
      name
    }
  }
}

In the response, cream was substituted with water which now makes the set of ingredients meet the requirement of being vegan.

{
  "data": {
    "dishes": [
      {
        "id": "171",
        "name": "Avocado Banana Kiwi Smoothie",
        "suggestedIngredients": [
          {
            "id": "17",
            "name": "avocado"
          },
          {
            "id": "22",
            "name": "banana"
          },
          {
            "id": "43",
            "name": "brown sugar"
          },
          {
            "id": "163",
            "name": "kiwi"
          },
          {
            "id": "385",
            "name": "water"
          }
        ]
      }
    ]
  }
}

In this case, the substituted ingredient was water, but let’s say for some reason it was substituted with a nutcream. Then our ingredients, which were previously nutfree, are not anymore. In those cases you could create a refresh query, to always be updated on which dietary requirements are currently met.

query refreshDiets($ingredients: [ID]){
  tags(shared: {type: INGREDIENT, ids: $ingredients}, category: "dietary"){
    id
    name
  }
}

In this case, we see the tag vegan was added, but also the tag lactosefree.

{
  "data": {
    "tags": [
      {
        "id": "16",
        "name": "glutenfree"
      },
      {
        "id": "17",
        "name": "vegan"
      },
      {
        "id": "18",
        "name": "No meat"
      },
      {
        "id": "19",
        "name": "lactosefree"
      },
      {
        "id": "21",
        "name": "nutfree"
      },
      {
        "id": "247",
        "name": "eggfree"
      }
    ]
  }
}

Lastly, instead of just having a set of ingredients, we can generate a recipe from them.

query recipe($dish: ID!, $ingredients: [ID]!){
  recipe(dish: $dish, ingredients: $ingredients){
    instructions{
      text
    }
  }
}

And here are the instructions for it!

{
  "data": {
    "recipe": {
      "instructions": [
        {
          "text": "Peel and slice the banana and kiwi."
        },
        {
          "text": "Scoop out the avocado."
        },
        {
          "text": "Add the avocado, banana, brown sugar, water and kiwi to your blender and blend until smooth."
        },
        {
          "text": "Serve the smoothie cold right away, or store it in the fridge up to 3 days."
        }
      ]
    }
  }
}