2017-01-13 6 views
2

Graphqlインスタンスとのインタフェースを使用していますが、おそらくこの問題は共用体にも当てはまります。 インターフェイスを実装するすべてのタイプに共通する2つのフィールドがありますが、各タイプには複数の追加フィールドがあります。GraphqlとApolloStackを使った共用体/インタフェースフィールドの解決方法

は、私はタイプごとに追加のフィールドを入手するにはどうすればよい次のスキーマ

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); 
    } 
    } 
} 

を考えると?

現在、idtypeの基本フィールドを取得するために、すべての食品を取得しています。allFoodその後、私は結果をループしています。タイプがPizzaのものが見つかった場合は、fetchFromPizzaEndpointに呼び出しを行い、追加フィールドを取得して元の基本タイプにマージします。私はこれを各タイプごとに繰り返します。

上記のように、特定のフィールド(Pizza.toppingsなど)で手動で特定のフィールドを解決することもできます。

私の解決策は理想的ではありません。単一のフィールドtoppingsと同じように、各タイプごとに複数のフィールドを解決することができます。これはGraphQLで可能ですか?これを実現するには、より良い方法が必要です。これは、一般的な使用例であるためです。

理想的には、自分のクエリで要求されているフラグメントを私のリゾルバで知ることができるようにするため、要求されるエンドポイント(1つのフラグメントあたり1つのエンドポイント)に対してのみコールできます。

{ 
    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); 
    } 
    } 
} 
+0

各データローダーから返されるものについて詳しく説明できますか?このユースケースは私にとってはかなり外見に見えますが、サーバ実装ではいくつかのユニオンタイプのケースがあります。私たちにとっては、ユニオンに含まれているデータをDBから取り込みます(それ以上のデータをすべてロードする必要はありません)。そして、GraphQLがデータを(型リゾルバで)返すべき型を決定します。 – ephemer

+0

DataLoadersは単にデータをフェッチするFacebook DataLoaderであり、データのソースは重要ではありません。現在、私はあなたが述べたとおりに正確にやっていますが、私が使用するよりも多くのデータを取得する必要があるため、非効率です。たとえば、「ピザ」を断片化するだけでは、「サラダ」のプロパティを下げてはいけません。フラグメントレベルリゾルバを持つことは素晴らしいことですが、GraphQL開発者と話した後、将来の機能であり、現在サポートされていないようです。 – JustinN

+0

それは私が理解していないビットです。あなたのデータが実際にピザの場合、Saladのプロパティはどのように取得しますか?そのため、DataLoaderによって返されるデータは重要です。たとえば、MongoDBからデータをロードします。MongoDBからドキュメントをクエリすると、そのドキュメントに含まれているもの(つまり、ピザドキュメントの「ピザ」データのみ)とそれ以外は含まれません。そこに非効率的なことはありません。 GraphQLから返されるデータに非効率性があることを意味するなら、それはあなたにとって完全にユニオンタイプが扱うものです。それがあなたが心配している非効率性であるなら、私はより詳細な答えを書くでしょう – ephemer

答えて

4

私はこの質問が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); 
     } 
    } 
} 

のような構造に彼のレゾルバを通過している。しかし、彼は本当に何か

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

(ない正確に、私は、クエリに__resolveTypeの位置を強調しています)などの公式ドキュメントは例を持っていたかったですhereですが、インターフェイスの種類のみが含まれていますが、混乱しています。私はユニオンタイプ(インタフェースと同じように設定されている)の追加の完全な実行可能な例を持っていますhere

+0

数週間前に完全に書き直しました。上記のとおりです。ほとんど私がここでこの質問を忘れていた:) – JustinN

関連する問題