Graphql过滤器查询结果

时间:2020-10-17 03:54:09

标签: javascript graphql apollo

我是使用graphql的新手,我想改善我的API的某些功能,其中之一是获得更好的过滤器。 此API应该根据用户将在相应APP中告知的成分返回一些配方,这是我正在使用的解析器:

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'),
  }}

服务

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
  }

查询架构

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
  }

过滤器正在工作,但我想改进2件事:

  1. 当我看到没有返回图graphql“游乐场”时,当成分没有任何值时(即在与食谱不同的表中),则成分值为“ null”,我什至不希望返回食谱。
  2. 我无法使过滤器正常工作。例如,我创建了查询类型“ recipe(name:[String]):[Recipe]”,但是我不知道如何从那里过滤它。这意味着,我想对查询进行成分过滤,按预期过滤结果

查询: 食谱(名称:[“ sal”,“açucar”,“ farinha”]){ ID 标题 作者 链接 类别 子类别 配料{ 名称 数量 测量 观察 } }

但是如您所见,解析器是硬代码,如何将过滤器发送到解析器?

有人可以帮我吗? 非常感谢。

2 个答案:

答案 0 :(得分:2)

通常,为了处理过滤,我设置创建一个Condition类型,该类型基于上下文命名。在这里,也许您想传递类型RecipeCondition,该类型定义字段以有效地过滤或确定返回的配方的范围,例如,根据其在数据存储区中是否包含成分。假设您将来可能要添加其他条件(否则,可以仅在sql中对条件进行硬编码)。


    type RecipeCondition {
      ingredientsRequired: Bool
      
      // Add other condition fields here as needed
      ...
     }


   type Query {
     recipe(name:[String], condition: RecipeCondition): [Recipe]
       ...
    }

我将在顶层使用db服务获取配方的顶层处理过滤器(与在配料subresolver中处理相反)。您可以简单地使用此条件,该条件可在配方解析器arg上访问,并将其传递给最初获取配方数组的db服务函数。如果条件ingredientsRequiredtrue,则使用sql进行适当的过滤(将需要连接到配料表和whereIn条件-如果您传递配方名称数组,则可能需要迭代完成)。这样,没有成分的配方甚至都不会击中成分子解析器(假设满足条件)。

答案 1 :(得分:1)

感谢所有尝试提供帮助的人,所有这些评论对于指导最终答案非常重要。 我得到了一个可行的解决方案,如果可能的话,我想分享并获取您的反馈。

首先,我改进了查询解析器

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

第二,我更改了服务以接收过滤器

 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

现在一切正常,并按预期进行过滤。

再次感谢大家。