Оба предназначены для того, чтобы помочь вам разработать схему с гетерогенным набором типов, и вы можете достичь одинаковой функциональности с использованием обоих, но 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
всеми объектами, использующими интерфейс.
когда вы запрашиваете «блоги» на фрагменте ретрансляции, что это соответствует графику? Я вижу, что ваш тип интерфейса graphql называется 'Blog' – maxwell
Вам нужно будет создать запрос' blogs', который не находится в образце кода –
Я все еще не уверен, что понимаю – arcom