Циклическая схема выдает ошибку "Ошибка: схема должна содержать уникальные именованные типы, но содержит несколько типов с именем" Узел "."

Я новичок в GraphQL с использованием nodejs. Я застрял в двунаправленном отображении схемы. посты <-> авторов. Использование graphql и graphql-relay модуля.

Ниже приведены две схемы, которые мы используем.

--posts.js // here we are requiring authors.js 
const {
    AuthorType,
    schema: AuthorSchema,
    AuthorsConnection
} = require('./authors');

class Post {}

const {
    nodeInterface,
    nodeField
} = nodeDefinitions(
    globalId => {
        const {
            type,
            id
        } = fromGlobalId(globalId);
        // return based on the id
        return DataSource['posts'][0];
    },
    obj => {
        console.log(" : PostType : ", PostType);
        // type to be return 
        return Post;
    }
);

const PostType = new GraphQLObjectType({
    "name": "PostType",
    "description": "Posts type and it's relevant fields",
    "fields": () => ({
        "id": globalIdField('Post'),
        "title": {
            "type": GraphQLString
        },
        "body": {
            "type": GraphQLString
        },
        "author": {
            "type": AuthorsConnection,
            "resolve": (parent, argument, root, currentSdl) => {
                console.log("v1, v2, v3, v4  :", parent);
                if (parent.author)
                    return connectionFromArray(DataSource['authors'], {})
                return [];
            }
        }
    }),
    isTypeOf: Post,
    interfaces: [nodeInterface]
});

const {
    connectionType: PostsConnection,
    edgeType: GQLPostEdge
} = connectionDefinitions({
    name: "Post",
    nodeType: PostType
});
module.exports = exports = {
    PostType,
    PostsConnection,
    schema: {
        post: nodeField,
        posts: {
            type: PostsConnection,
            resolve: (root, v2, v3) => {
                return connectionFromArray(DataSource['posts'], {});
            }
        }
    }
};

--authors.js // here we have required posts.js

const {
    PostType,
    PostsConnection
} = require('./posts');

class Author {}

const {
    nodeInterface,
    nodeField
} = nodeDefinitions(
    globalId => {
        const {
            type,
            id
        } = fromGlobalId(globalId);
        // return based on the id
        return DataSource['authors'][0];
    },
    obj => {
        console.log(" : Authorype : ", Authorype);
        // type to be return 
        return Author;
    }
);

const AuthorType = new GraphQLObjectType({
    "name": "AuthorType",
    "description": "Author type and it's relevant fields",
    "fields": () => ({
        "id": globalIdField('Author'),
        "firstName": {
            "type": GraphQLString
        },
        "lastName": {
            "type": GraphQLString
        },
        authorPosts: {
            type: PostsConnection,
            resolve: (parent, args, root, context) => {
                return connectionFromArray(DataSource['posts'], {});
            }
        }
    }),
    isTypeOf: null,
    interfaces: [nodeInterface]
});

const {
    connectionType: AuthorsConnection,
    edgeType: GQLAuthorEdge
} = connectionDefinitions({
    name: "Author",
    nodeType: AuthorType
});

module.exports = exports = {
    AuthorType,
    AuthorsConnection,
    schema: {
        author: nodeField,
        authors: {
            type: AuthorsConnection,
            resolve: (root, v2, v3) => {
                return connectionFromArray(DataSource['authors'], {});
            }
        }
    }
};

Как только я объединяю вышеуказанную схему для GraphQL, я получаю следующую ошибку.

Error: Schema must contain unique named types but contains multiple types named "Node".

Я попытался отладить эту проблему, после чего я заметил следующее.

  • Как только я меняю поле "авторы" со схемы сообщений на другое, чем "AuthorsConnection", оно начинает работать.
  • Или, если удалено поле "авторы" из схемы сообщений, оно начинает работать.

Пожалуйста, дайте мне знать, что проблема здесь, это имеет отношение к nodeDefinitions функционировать?

2 ответа

Решение

Это действительно связано с nodeDefinitions функция. От graphql-relay документы:

nodeDefinitions возвращает Node интерфейс, который объекты могут реализовать, и возвращает node корневое поле для включения в тип запроса. Чтобы реализовать это, требуется функция для разрешения идентификатора объекта и определения типа данного объекта.

Вы звоните это дважды, что приводит к Node тип определяется дважды, и вы ссылаетесь на один из них:

schema: {
    post: nodeField,

// ...

schema: {
    author: nodeField,

Это вызывает ошибку - теперь есть два независимых экземпляра Node который недействителен.

Решение состоит только в том, чтобы позвонить nodeDefinitions один раз, а затем передать ссылку на сгенерированный nodeField а также nodeInterface в соответствующие места. Тогда ваш globalId => {...} Функция должна будет смотреть на type выяснить, как получить соответствующую запись, будь то автор или пост.

Вместе с ответом выше, данным @Benjie. Я нахожу способ преодолеть проблемы, которые привели к ошибке Error: Schema must contain unique named types but contains multiple types named "Node".,

Ниже приведены ключевые моменты, которые нужно проверить, когда мы создаем graphql модульным способом.

  • Не создавайте новые экземпляры типа, например: const PostType = new GraphQLObjectType({}) он должен всегда отправлять один объект, а не новый объект каждый раз.
  • использование nodeDefinations только однажды.
  • Проверьте наличие циклических проблем в распространенной проблеме JavaScript, которая возникнет.

Благодарю.

Другие вопросы по тегам