首页 文章

如何使用GraphQL和ApolloStack解析union / interface字段

提问于
浏览
3

我正在使用我的GraphQL实例的接口,但这个问题也许适用于工会 . 实现接口的所有类型都有2个公共字段,但每种类型上都有多个附加字段 .

给出以下架构

interface FoodType {
  id: String
  type: String
}

type Pizza implements FoodType {
  id: String
  type: String
  pizzaType: String
  toppings: [String]
  size: String
}

type Salad implements FoodType {
  id: String
  type: String
  vegetarian: Boolean
  dressing: Boolean
}

type BasicFood implements FoodType {
  id: String
  type: String
}

以及解决方案

{
  Query: {
    GetAllFood(root) {
      return fetchFromAllFoodsEndpoint()
        .then((items) => {
          return mergeExtraFieldsByType(items);
        });
    },
  },
  FoodType: {
    __resolveType(food) {
      switch (food.type) {
        case 'pizza': return 'Pizza';
        case 'salad': return 'Salad';
        default: return 'BasicFood';
      }
    },
  },
  Pizza: {
    toppings({pizzaType}) {
      return fetchFromPizzaEndpoint(pizzaType);
    }
  }
}

如何获取每种类型的附加字段?

目前,我有 allFood 获取所有食物以获得 idtype 的基本字段 . 在此之后我循环结果,如果找到 Pizza 类型的任何一个,我调用 fetchFromPizzaEndpoint ,获取其他字段并将它们合并到原始基本类型上 . 我为每种类型重复一遍 .

我也能够手动解析特定字段,一个类型,例如 Pizza.toppings ,如上所示 .

现在我的解决方案并不理想,我宁愿能够为每种类型解析多个字段,就像我使用单个字段 toppings 一样 . GraphQL可以实现吗?必须有更好的方法来实现这一点,因为这是一个非常常见的用例 .

理想情况下,我希望能够在我的解析器中知道我的查询要求的片段,因此我只能调用要求的 endpoints (每个片段一个 endpoints ) .

{
  Query: {
    GetAllFood(root) {
      return fetchFromAllFoodsEndpoint();
    },
  },
  FoodType: {
    __resolveType(food) {
      switch (food.type) {
        case 'pizza': return 'Pizza';
        case 'salad': return 'Salad';
        default: return 'BasicFood';
      }
    },
  },
  Pizza: {
    __resolveMissingFields(food) {
      return fetchFromPizzaEndpoint(food.id);
    }
  },
  Salad: {
    __resolveMissingFields(food) {
      return fetchFromSaladEndpoint(food.id);
    }
  }
}

1 回答

  • 5

    我知道这个问题是5个月大,但我希望这可以帮助其他人解决这个问题 . 他正在通过他的解析器结构

    {
        Query: {
            GetAllFood(root) {
            return fetchFromAllFoodsEndpoint()
                .then((items) => {
                return mergeExtraFieldsByType(items);
                });
            },
        },
        FoodType: {
            __resolveType(food) {
            switch (food.type) {
                case 'pizza': return 'Pizza';
                case 'salad': return 'Salad';
                default: return 'BasicFood';
            }
            },
        },
        Pizza: {
            toppings({pizzaType}) {
            return fetchFromPizzaEndpoint(pizzaType);
            }
        }
    }
    

    但他真的想要类似的东西(不完全是,但我强调__resolveType相对于Query的位置)

    {
        Query: {
            GetAllFood(root) {
            return fetchFromAllFoodsEndpoint()
                .then((items) => {
                return mergeExtraFieldsByType(items);
                });
            },
        },
        FoodType: {
            __resolveType(data, ctx, info) {
                return whatIsTheType(data, ctx, info)
            }
        }
    }
    

    官方文档有一个示例here,但它只包含接口类型,我发现这令人困惑 . 我有一个额外的完整可运行的Union类型示例(配置与接口相同)here

相关问题