【发布时间】:2017-05-28 14:19:57
【问题描述】:
我在我的 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获取所有食物以获取id和type的基本字段。在此之后,我将遍历结果,如果发现任何Pizza 类型,我将调用fetchFromPizzaEndpoint,获取附加字段并将它们合并到原始基本类型中。我对每种类型都重复此操作。
我还能够手动解析特定字段,一个类型,例如Pizza.toppings,如上所示。
现在我的解决方案并不理想,我更希望能够为每种类型解析多个字段,就像我对单个字段 toppings 所做的那样。 GraphQL 可以做到这一点吗?必须有更好的方法来实现这一点,因为这是一个很常见的用例。
理想情况下,我希望能够在我的解析器中知道我的查询需要哪些片段,因此我只能调用被请求的端点(每个片段一个端点)。
{
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);
}
}
}
【问题讨论】:
-
能否详细说明每个dataLoader返回的内容是什么?这个用例对我来说看起来很陌生,尽管在我们的服务器实现中确实有几个联合类型的案例。对我们来说,我们从数据库中获取联合包含的任何数据(此时我们已经拥有所有数据而无需加载更多数据),然后决定 GraphQL 应该返回哪种类型的数据(在它的类型解析器)。
-
DataLoader 只是获取数据的 Facebook DataLoader,数据的来源并不重要。目前,我正在按照您提到的那样做,但是效率低下,因为我必须获取比我将要使用的更多的数据。例如,如果我只对“Pizza”进行分段,则不应将“Salad”属性下拉。拥有片段级解析器会很棒,但在与 GraphQL 开发人员交谈后,它似乎是一个未来的功能,目前不支持。
-
这是我不明白的一点。如果您的数据实际上是披萨,您将如何获得沙拉属性?这就是为什么 DataLoader 返回哪些数据很重要的原因。例如,我们从 MongoDB 加载数据。如果您从 MongoDB 查询文档,它包含它所包含的内容(即,只有 Pizza 文档的“Pizza”数据)而没有其他内容。那里没有效率低下。如果您的意思是从 GraphQL 返回的数据效率低下,那么联合类型可以完美地为您处理。如果那是您担心的效率低下,我会写一个更详细的答案
-
您可以直接调用数据库并按照您认为合适的方式构建查询(在本例中为 MongoDb),而在我的实例中,我正在与许多 REST Web 服务交谈。所以我打电话给 Query.GetAllFood - 这会影响服务以获得一切。但是,如果我执行“... on Pizza { toppings }”的片段,我想知道该片段并调用另一个 Web 服务端点来获取披萨数据并将其合并到我的结果中。目前我调用所有服务并合并所有不是一个很好的解决方案。
-
您能否更新您的问题以包含该信息?我个人觉得没有它很难理解。当我有时间时,如果我有一个问题,我会写一个回答你的问题。事实上,如果你完全删除所有提及
dataLoader并只使用fetchFromPizzaEndpoint()、fetchFromAllFoodsEndpoint()等内容会更好。
标签: node.js graphql apollostack