2016-01-11 19 views

risposta

1

Il semantico di GraphQLInterfaceType è come la maggior parte del linguaggio di programmazione interface. e graphql aggiunge altri comportamenti per questo. come verificare se la classe derivata implementa tutti i campi, risolvendo dinamicamente l'istanza derivata.
La Sematic di GraphQLUnionType non è un Union, ma qualcosa di simile OR. (Un po 'come il tipo di controllo flowtype?)
Un esempio reale è example in Relay => progettazione del nodo del relè.
GraphQLInterfaceType non è completamente correlato a GraphQLUnionType.
Penso che tu sia stato confuso da questo?

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 
} 

Se essere confusi da questo, si dovrebbe ottenere qualche libro di un linguaggio forte tipo da leggere. (Come C# o Java o qualcos'altro. Forse si dovrebbe dare un'occhiata a Portata troppo, questo utilizzo Dog|Cat è un tipo limitazione)

17

Entrambi hanno lo scopo di aiutarti a progettare uno schema con un insieme eterogeneo di tipi e potresti ottenere la stessa funzionalità utilizzando entrambi, ma GraphQLInterfaceType è più adatto quando i tipi sono sostanzialmente uguali ma alcuni dei campi sono diversi e GraphQLUnionType quando i tipi sono completamente diversi e hanno campi completamente diversi.

In definitiva se utilizzare l'uno o l'altro in base alla progettazione dello schema.

Per un esempio reale, supponiamo di avere un elenco di blog, ma i blog che utilizzano framework A utilizzano nome utente e password come autenticazione e il blog che utilizza il framework B utilizza email e password. Progettiamo con una GraphQLInterfaceType come questo:

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

Quando creiamo un nuovo blog invio username, si creerà una BlogA.

possiamo interrogare in questo modo:

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

Ora iniziamo la stessa funzionalità ma usando GraphQLUnionType, perché noi preferiamo usare semplicemente un tipo di blog, e 2 tipi di metodi di autenticazione:

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

possiamo interrogare in questo modo:

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

come si può vedere in in questo esempio otteniamo la stessa cosa con l'interfaccia o l'unione, ma l'una o l'altra potrebbe essere più appropriata in base alla progettazione dello schema.

Ad esempio, supponiamo di voler aggiungere un framework C per il blog che utilizzi anche e-mail e password. Dovresti includere un altro campo per poterlo distinguere dal framework B del blog nella nostra funzione resolveBlogType. Aggiungiamo il campo type. Nel nostro esempio dell'Unione, poiché abbiamo solo accesso ai campi all'interno dell'Unione, è necessario aggiungere type all'Unione. Se in futuro volessimo aggiungere un'altra Unione con gli stessi campi per più framework, dovremmo aggiungere anche il campo type. Non è così bello avere type duplicato più volte nel nostro schema. Potrebbe essere un'idea migliore utilizzare un'interfaccia e avere un singolo campo type accessibile dalla funzione resolveBlogType da tutti gli oggetti che utilizzano l'interfaccia.

+0

quando si esegue una ricerca per 'blogs' sul frammento relay che cosa è corrispondente a graphql-wise? Vedo che il tuo tipo di interfaccia graphql si chiama 'Blog' – maxwell

+0

Dovresti creare la query' blogs', che non è nel codice di esempio –

+0

Non sono ancora sicuro di aver capito – arcom