2017-01-09 13 views
1

私はGraphQLを私のいくつかのREST APIの代わりに探していましたが、私は基本的なことを頭の中に入れてしまったと思っています。 1つの重要な機能が欠落しているようです。GraphQLレスポンスのカスタムマップキー

のは、私はこのようなアイテムのコレクションを持っているとしましょう:

アプリケーションのようなIDによってインデックスを作成したすべてのそれらのオブジェクトのマップ、必要

{ 
    "id": "aaa", 
    "name": "Item 1", 
    ... 
} 

{ 
    "allItems": { 
     "aaa": { 
      "name": "Item 1", 
      ... 
     }, 
     "aab": { 
      "name": "Item 2", 
      ... 
     } 
    } 
} 

すべてのAPIのIを今まで書かれたことは、このような形式で結果を返すことができましたが、私はGraphQLでそれを行う方法を見つけるのに苦労しています。私はissue 101を走り続けていますが、それは未知のスキーマを多く扱っています。私の場合、私はすべてのフィールドが何であるかを正確に知っています。純粋に出力フォーマットです。私は単純に配列のすべての項目を返すことができ、それをクライアント側で再フォーマットすることができることを知っていますが、過去には一度も必要とされなかったことを考えると、私がしようとしていることが不可能なのかどうか、あるいは間違った用語を使っているだけなのかどうかは分かりません。私は掘り続けなければならないのですか、GraphQLは自分のニーズに合っていませんか?これが可能であれば、このようなデータを取得するためにクエリはどのように見えますか?

私は現在サーバー上でgraphql-phpと仕事をしていますが、私はより高いレベルの概念的な回答に対応しています。

+0

"GraphQLを後ろ向きに感じさせます" - あなたの場合、おそらく、Webサービスの各クライアントが必要とするものを知っているでしょう。それ以外の場合、マップはクライアントが必要とするものであると仮定しています。 Webサービスが返すものとは正反対のものを必要とするクライアントは、何らかの変換を行う必要があります。 IMHOでは、マップや配列スタイルのコレクションを返すかどうかの決定は、クライアントがどちらか一方を望むかどうかにかかわらず50:50であるため、洗い場になります。 – CommonsWare

+0

@CommonsWare私が現時点で気付いているAPIは、組織の内部でのみ使用されているので、すべてのクライアントがいつもそれを入手している形式のデータを必要としていると確信できます。ページの読み込みをローカル検索のためのクイックインデックスとして使用し、必要に応じて拡張された項目の詳細を(GraphQLで簡単に表現できる形式で)取得します。問題は単純に私がしようとしていることが可能かどうかです。 –

+0

"すべてのクライアントは、常にそれを入手してきた形式でデータを必要とする" - コレクションをマップに変換することは、最新のプログラミング言語では1〜3行のコードを要する。 "GraphQLは自分のニーズに合っていないのですか?" - Webサービスで特定のJSON構造体を返す必要がある場合、GraphQLは適切ではありません。あなたがこのケースを過ぎても(そして解決策がわからない)、あなたは何か他のものを打つでしょう。スキーマによって決まるJSONの構造を完全に制御することはできず、スキーマは任意の構造を扱うように設計されていません。 – CommonsWare

答えて

5

残念ながら、このような任意の動的キーを持つオブジェクトを返すことは、実際にはGraphQLのファーストクラスの市民ではありません。それはあなたが同じことを達成できないと言っているわけではありませんが、そうすることでGraphQLの多くの利点が失われます。

IDを含むオブジェクトのコレクション/リストを返す代わりにidキーを持つオブジェクトを返すときに設定し、クライアントで変換を実行すると、特別なGraphQLScalarTypeを作成できます。

const GraphQLAnyObject = new GraphQLScalarType({ 
    name: 'AnyObject', 
    description: 'Any JSON object. This type bypasses type checking.', 
    serialize: value => { 
    return value; 
    }, 
    parseValue: value => { 
    return value; 
    }, 
    parseLiteral: ast => { 
    if (ast.kind !== Kind.OBJECT) { 
     throw new GraphQLError("Query error: Can only parse object but got a: " + ast.kind, [ast]); 
    } 
    return ast.value; 
    } 
}); 

このアプローチの問題点は、スカラ型であるため、クエリを実行するための選択セットを提供できないことです。例えば。あなたがタイプ

type MyType implements Node { 
    id: ID! 
    myKeyedCollection: AnyObject 
} 

を持っていたなら、あなたはだけなので

query { 
    getMyType(id: abc) { 
    myKeyedCollection # note there is no { ... } 
    } 
} 

他の人が言ったようにあなたが利益の多くを失っているので、私はこれをお勧めしませんようにそれを照会することができるだろうしかし、GraphQLはまだRESTができることは何でもできることを示しています。試してみたいのであれば、scaphold.ioのAnyObject型を用意しています。

希望すると便利です。