Search code examples
javascriptgraphqlapollo

Graphql filter query result


I am new using graphql and I would like to improve some features at my API, one of the is get a better filter. This API should return some recipe base on the ingredients that the user will inform in the respective APP, This is The resolver I am using:

module.exports = {
  Recipe: {
    async ingredients(recipe, _, { dataSources }) {
      return await dataSources.IngredientService.getRecipeIngredients(recipe.id)
    },
  },
  Query: {
    recipe: async () =>  db('Recipe'),
    ingredient: async () => db('Ingredient'),
    recipeByIngredient:async () => db('Recipe'),
  }}

the service

class ingredientService {
  async getRecipeIngredients(recipe_id) {
      const filteredRecipe = db('Ingredient')
      .where({ recipe_id })
      .join('Recipe', 'Recipe.id', '=', recipe_id)
      .select('Recipe.*', 'Ingredient.*')
      .whereIn('Ingredient.name', ["sal", "açucar"])
      return await filteredRecipe
  }

the query schema

type Query {
  recipe(name:[String]): [Recipe]
  ingredient:[Ingredients]
  recipeByIngredient(ingredients:String):[Ingredients]
}
type Recipe {
  id: Int
  title: String!
  author: String
  link: String
  category: String
  subcategory:String
  ingredients:[Ingredients]
}

type Ingredients{
    id:Int
    name:String
    quantity:Float
    measure:String
    observation:String
  }

The filter is working but I would like ot improve 2 things:

  1. When I see the return no the graphql "playground", when there is no value to the ingredient (that is in on different table from recipes), then the ingredient value is "null" and I would like to not even return the recipe.
  2. I could not make the filter work. I reated the query type "recipe(name:[String]): [Recipe]", for example, but I do not know how to filter it from there. It means, I would like to ingredients filter over my query, filtering the result as expected

quer: recipe(name :["sal", "açucar", "farinha"]){ id title author link category subcategory ingredients{ name quantity measure observation } }

but as you can see, the resolver is hardcode, how could I sent the filter to the resolver?

can anyone help me on it? Thanks a lot.


Solution

  • Thank you all that tried to help, all these comments was very important to guide to the final answer. I got one posible solution, that I would like to share and get your feedback, if posible.

    On first, I improved my Query resolver

      Query: {
        recipe(obj, {name}, {dataSources}, info) {
          if (name) {
            return dataSources.IngredientService.getIngredientsByName(name)
          } else {
            return db('Recipe')  
          }
        }
    

    Second, I changed my Service to receive the filter

     async getIngredientsByName(name) {
        const filteredRecipe = db('Ingredient')
        //.where({ recipe_id })
        .join('Recipe', 'Recipe.id', '=', 'Ingredient.recipe_id')
        .select('Recipe.*', 'Ingredient.name', 'Ingredient.quantity', 'Ingredient.measure','Ingredient.observation')
        .whereIn('Ingredient.name', name)
        return await filteredRecipe
    

    now is everything working fine and making the filter as expected.

    Once again, thanks a lot, all of you.