Cyclic schema giving error as "Error: Schema must contain unique named types but contains multiple types named "Node"."

Cyclic schema giving error as "Error: Schema must contain unique named types but contains multiple types named "Node"."

我是 'GraphQL' 使用 nodejs 的新手。我被困在双向模式映射中。帖子 <-> 作者。使用 graphql and 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".

我试着调试了这个问题,下面是我观察到的。

请告诉我这里有什么问题,它与 nodeDefinitions 功能有关吗?

确实与nodeDefinitions功能有关。来自 graphql-relay 文档:

nodeDefinitions returns the Node interface that objects can implement, and returns the node root field to include on the query type. To implement this, it takes a function to resolve an ID to an object, and to determine the type of a given object.

您调用了两次,这导致 Node 类型被定义了两次,并且您引用了每个类型之一:

schema: {
    post: nodeField,

// ...

schema: {
    author: nodeField,

这是导致错误的原因 - 现在有两个无效的 Node 实例。

解决方法是只调用一次nodeDefinitions,然后将生成的nodeFieldnodeInterface的引用传到相关的地方。然后你的 globalId => {...} 函数将需要查看 type 来弄清楚如何获取相关记录,无论是作者还是 post.

以及@Benjie 给出的上述答案。我找到了解决导致 Error: Schema must contain unique named types but contains multiple types named "Node"..

错误的方法

以下是我们在以模块化方式制作graphql时需要检查的关键点。

  • 不要创建类型的新实例,例如:const PostType = new GraphQLObjectType({})它应该始终发送单个对象而不是每次都发送新对象。
  • 仅使用 nodeDefinations 一次。
  • 检查常见的循环问题 javascript 会发生的问题。

谢谢。