我是新使用graphql的,我想改进API的一些功能,其中之一是获得更好的过滤器。这个API应该返回一些基于成分的配方,用户将在各自的应用程序中通知,这是我正在使用的解析器:
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
}
过滤器正在工作,但我想改进两件事:
- 当我看到返回no时,graphql"操场";,当配料没有值时(在与配方不同的表中(,则配料值为"0";空";我甚至不想退回菜谱
- 我无法使过滤器工作。我创建了查询类型";recipe(名称:[String](:"recipe]";,例如,但我不知道如何从那里过滤它。这意味着,我想对我的查询进行成分过滤,按预期过滤结果
quer:配方(名称:["sal","açucar","fariha"]({id标题著者链接类别子类别配料{名称量测量观察}}
但正如你所看到的,解析器是硬编码的,我怎么能把过滤器发送到解析器?
有人能帮我吗?非常感谢。
通常,为了处理过滤,我设置创建一个基于上下文命名的Condition
类型。在这里,您可能希望传递一个类型RecipeCondition
,它定义字段来有效地过滤或确定返回的配方的范围,例如,根据它在数据存储中是否包含成分。这假设您将来可能想要添加额外的条件(否则,可能只是在sql中对条件进行硬编码(。
type RecipeCondition {
ingredientsRequired: Bool
// Add other condition fields here as needed
...
}
type Query {
recipe(name:[String], condition: RecipeCondition): [Recipe]
...
}
我会在最高层处理过滤器,在那里你最初用db服务获取食谱(而不是在配料子求解器中处理(。您可以简单地使用这个条件(可在配方解析程序arg上访问(,并将其传递给最初获取配方数组的db服务函数。如果条件ingredientsRequired
是true
,则使用sql进行适当的过滤(需要联接到配料表和where In条件中——如果您传递一个配方名称数组,则可能需要迭代完成(。这样,没有配料的配方甚至不会进入配料子求解器(假设需要该条件(。
感谢所有试图提供帮助的人,所有这些评论对于指导最终答案非常重要。我有一个可行的解决方案,如果可行的话,我想分享并获得您的反馈。
首先,我改进了我的查询解析器
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
现在一切都很好,并按预期制作过滤器。
再次感谢大家。