Динамическое создание схемы graphql с циклическими ссылками

Используя graphql-js, мне нужно динамически создать схему graphql, перебирая массив некоторых данных, например:

[{
    name: 'author',
    fields: [{
        field: 'name'
    }, {
        field: 'books',
        reference: 'book'
    }]
}, {
    name: 'book',
    fields: [{
        field: 'title'
    }, {
        field: 'author',
        reference: 'author'
    }]
}]

Проблема в циклических ссылках. Когда я создаю AuthorType, мне нужно, чтобы BookType уже был создан, и наоборот.

Таким образом, результирующая схема должна выглядеть так:

type Author : Object {  
  id: ID!
  name: String,
  books: [Book]
}

type Book : Object {  
  id: ID!
  title: String
  author: Author
}

Как я могу это решить?


person User Created Image    schedule 31.08.2016    source источник
comment
Используйте fieldconfigmapthunk graphql.org/docs/api-reference-type-system   -  person vbranden    schedule 02.09.2016


Ответы (2)


Цитата из официальной документации

http://graphql.org/docs/api-reference-type-system/

Когда два типа должны ссылаться друг на друга или тип должен ссылаться на себя в поле, вы можете использовать функциональное выражение (также известное как замыкание или преобразователь) для ленивой подачи полей.

var AddressType = new GraphQLObjectType({
  name: 'Address',
  fields: {
    street: { type: GraphQLString },
    number: { type: GraphQLInt },
    formatted: {
      type: GraphQLString,
      resolve(obj) {
        return obj.number + ' ' + obj.street
      }
    }
  }
});

var PersonType = new GraphQLObjectType({
  name: 'Person',
  fields: () => ({
    name: { type: GraphQLString },
    bestFriend: { type: PersonType },
  })
});

Также посмотрите на этот связанный ответ циклических типов категорий и подкатегорий.

person LordDave    schedule 02.09.2016
comment
Этот ответ почти правильный, это правда, что вы должны использовать функциональное выражение. Кроме того, вам нужно дважды перебирать ваши данные. В первой итерации вы создаете все типы, но функция полей возвращает ссылки на пустые объекты. И во второй литерации вам нужно заполнить эти пустые объекты фактическими данными. - person User Created Image; 26.10.2016

Я решил эту проблему, используя преобразователь для поля fields.

const User = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLID }
  })
});

Когда вы делаете свои поля преобразователь, а не литерал объекта, вы можете использовать типы, которые определены позже в файле.

См. этот пост для получения дополнительной информации способ избежать циклических зависимостей в GraqhQL?

Основываясь на этом посте, я думаю, что это правильный способ сделать это.

person Benjamin Conant    schedule 14.10.2017