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.
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
Dovresti creare la query' blogs', che non è nel codice di esempio –
Non sono ancora sicuro di aver capito – arcom