15

GraphQLInterfaceTypeとをいつ使うべきか理解するのに苦労していますGraphQLUnionType

私はRTFMを持っています:

これらが私の厚い頭を理解するのに役立つ場合、誰かが実際の例を提供できますか?

4

2 に答える 2

32

どちらも、異種の型のセットを使用してスキーマを設計するのに役立つことを意図しており、両方を使用して同じ機能を実現できますが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
     }
   }
}

GraphQLUnionType1 種類のブログと 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 を追加するとします。関数内のブログ フレームワーク B と区別できるようにするには、別のフィールドを含める必要がありresolveBlogTypeます。typeフィールドを追加しましょう。ユニオンの例では、ユニオン内のフィールドにしかアクセスできないためtype、ユニオンに追加します。将来、複数のフレームワークに同じフィールドを持つ別のユニオンを追加したい場合は、typeそこにもフィールドを追加する必要があります。type私たちのスキーマで複数回複製したのはあまり良くありません。インターフェースを使用し、インターフェースを使用するすべてのオブジェクトが関数で単一のtypeフィールドにアクセスできるようにすることをお勧めします。resolveBlogType

于 2016-05-09T12:30:51.667 に答える
2

のセマティックGraphQLInterfaceTypeは、ほとんどのプログラム言語のinterface. そしてgraphqlはそれにいくつかの動作を追加します。派生クラスがすべてのフィールドを実装しているかどうかを確認し、派生インスタンスに動的に解決します。
のセマティックはGraphQLUnionTypeではなく、 のUnionようなものORです (flowtype の型チェックに少し似ていますか?)
実際の例は Relay => Relay の Node design の例です。
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
}

Dog|Catこれに戸惑う場合は、強力な型言語の本を読む必要があります。

于 2016-02-02T08:52:25.260 に答える