2016-01-11 2 views
11

Мне сложно понять, когда использовать GraphQLInterfaceType и GraphQLUnionType.Пример реального мира GraphQLInterfaceType и GraphQLUnionType

Я RTFMs:

Может кто-нибудь предложить на реальный пример, когда это было бы полезно, чтобы получить его через мой толстый голову?

ответ

1

Сематик GraphQLInterfaceType похож на большинство программных языков interface. и graphql добавить еще несколько поведений для него. например, проверить, реализует ли производный класс все поля, динамическое разделение на производный экземпляр.
Sematic из GraphQLUnionType не 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 или что-то другое. Может быть, вы должны смотреть на Flow тоже это использование 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, которая также использует электронную почту и пароль. Вам нужно будет включить другое поле, чтобы можно было отличить его от блоговой рамки B в нашей функции resolveBlogType. Давайте добавим поле type. В нашем примере Союза, поскольку у нас есть только доступ к полям в Союзе, вы должны добавить type в Союз. Если в будущем мы хотели бы добавить еще один союз с одинаковыми полями для нескольких фреймворков, нам нужно будет также добавить поле type. Не очень приятно иметь type дублировать несколько раз в нашей схеме. Лучше было бы использовать интерфейс и иметь одно поле type, доступное в функции resolveBlogType всеми объектами, использующими интерфейс.

+0

когда вы запрашиваете «блоги» на фрагменте ретрансляции, что это соответствует графику? Я вижу, что ваш тип интерфейса graphql называется 'Blog' – maxwell

+0

Вам нужно будет создать запрос' blogs', который не находится в образце кода –

+0

Я все еще не уверен, что понимаю – arcom