2016-01-11 21 views
11

GraphQLInterfaceTypeGraphQLUnionTypeをいつ使用するのかを理解するのは苦労しています。GraphQLInterfaceTypeとGraphQLUnionTypeの現実世界の例

私はRTFMsました:これらは私の厚い頭を通してそれを得るために有用であろうとき

は、誰もが現実世界の例を提供することはできますか?

答えて

1

GraphQLInterfaceTypeのsematicはほとんどのプログラム言語のinterfaceのようです。 graphqlはそれに対していくつかの動作を追加します。派生クラスがすべてのフィールドを実装しているかどうかのチェック、派生インスタンスへの動的解決。
GraphQLUnionTypeのsematicがUnionではありませんが、ORのようなもの。(少しflowtypeの型チェックのような?)
現実世界の例では、example in Relay =>リレーのノード設計です。
GraphQLInterfaceTypeは、GraphQLUnionTypeとはまったく関係ありません。
私は多分あなたがこれで混乱していたと思いますか?これによって混同している場合

interface Node{ 
    id: string 
} 

type Dog implements Node{ 
    id: string 
} 
type Cat implements Node{ 
    id: string 
} 
union Animal = Dog | Cat 

type User{ 
    node: Node 
    animal: Animal 
} 

は、あなたが読むことを強い型言語のいくつかの本を取得する必要があります。(C#やJavaまたは何か他のもののような。多分あなたは流れを見ている必要がありすぎて、この使用Dog|Catがありますタイプ制限)

17

異機種セットのスキーマを設計するのに役立ちますが、両方を使用して同じ機能を実現できますが、タイプが基本的に同じであるがフィールドのいくつかの場合は、GraphQLInterfaceTypeがより適していますタイプが全く異なり、まったく異なるフィールドがある場合はGraphQLUnionTypeとなります。

最終的には、スキーマ設計によってどちらか一方を使用するかどうか。

実際の例では、ブログのリストがあるとしますが、フレームワークAを使用するブログでは認証にユーザー名とパスワードを使用し、フレームワークBではブログで電子メールとパスワードを使用します。私たちは、このようなGraphQLInterfaceTypeでそれを設計します

const BlogType = new GraphQLInterfaceType({ 
    name: 'Blog', 
    fields: { 
    url: { type: new GraphQLNonNull(GraphQLString) } 
    password: { type: new GraphQLNonNull(GraphQLString) } 
    }, 
    resolveType: resolveBlogType 
}); 

const BlogAType = new GraphQLObjectType({ 
    name: 'BlogA', 
    interfaces: [Blog], 
    fields: { 
    url: { type: new GraphQLNonNull(GraphQLString) } 
    username: { type: new GraphQLNonNull(GraphQLString) }, 
    password: { type: new GraphQLNonNull(GraphQLString) } 
    } 
}); 

const BlogBType = new GraphQLObjectType({ 
    name: 'BlogB', 
    interfaces: [Blog], 
    fields: { 
    url: { type: new GraphQLNonNull(GraphQLString) } 
    email: { type: new GraphQLNonNull(GraphQLString) }, 
    password: { type: new GraphQLNonNull(GraphQLString) } 
    } 
}); 

function resolveBlogType(value) { 
    return value.username ? BlogAType : BlogBType; 
} 

我々はusernameを送信する新しいブログを作成すると、それはBlogAを作成します。

我々は次のように問い合わせることができます:

query MyQuery { 
    blogs: { 
    url 
    password 
    ... on BlogA { 
     email 
    } 
    ... on BlogB { 
     username 
    } 
    } 
} 

今度は、同じ機能を取得してみましょうが、GraphQLUnionTypeを使用して、我々はブログの単に一つのタイプを使用することを好むため、および認証方法の2種類:

const AuthAType = new GraphQLObjectType({ 
    name: 'AuthA', 
    fields: { 
    username: { type: new GraphQLNonNull(GraphQLString) }, 
    password: { type: new GraphQLNonNull(GraphQLString) } 
    } 
}); 

const AuthBType = new GraphQLObjectType({ 
    name: 'AuthB', 
    fields: { 
    email: { type: new GraphQLNonNull(GraphQLString) }, 
    password: { type: new GraphQLNonNull(GraphQLString) } 
    } 
}); 

const AuthType = new GraphQLUnionType({ 
    name: 'Auth', 
    types: [AuthAType, AuthBType] 
    resolveType: resolveAuthType 
}); 

const BlogType = new GraphQLInterfaceType({ 
    name: 'Blog', 
    fields: { 
    url: { type: new GraphQLNonNull(GraphQLString) } 
    auth: { type: AuthType } 
    }, 

}); 

function resolveAuthType(value) { 
    return value.username ? AuthAType : AuthBType; 
} 

我々はこのように問い合わせることができます:あなたが見ることができるように

query MyQuery { 
    blogs: { 
    url 
    auth { 
     ... on AuthA { 
     username 
     password 
     } 
     ... on AuthB { 
     email 
     password 
     } 
    } 
    } 
} 

この例では、インタフェースまたは共用体で同じことを達成していますが、スキーマ設計に応じて、どちらか一方がより適切かもしれません。

たとえば、電子メールとパスワードを使用するブログフレームワークCを追加したいとします。 resolveBlogType機能では、ブログフレームワークBと区別できるように別のフィールドを含める必要があります。 typeフィールドを追加してみましょう。 Unionの例では、Union内のフィールドにしかアクセスできないため、typeをUnionに追加します。将来、複数のフレームワークに同じフィールドを持つ連合を追加したい場合は、typeフィールドも追加する必要があります。私たちのスキーマでtypeが何度も重複しているのはあまりいいことではありません。インターフェイスを使用し、resolveBlogType関数でインターフェイスを使用するすべてのオブジェクトによって単一のtypeフィールドにアクセスできるようにすることをお勧めします。

+0

リレーフラグメントで 'blogs'をクエリすると、これはgraphql-wiseに相当しますか?あなたのgraphqlインターフェイスタイプが 'Blog'という名前であることがわかります – maxwell

+0

サンプルコードにないブログのクエリを作成する必要があります –

+0

私はまだ分かりません – arcom

関連する問題