Graphql 连接、边、节点:如何使用节点的子类型

Graphql 连接、边、节点:如何使用节点的子类型,graphql,Graphql,我正在关注阿波罗的连接、边缘、节点和中继概念。 我使用节点{id:id!}接口。我收集了各种各样的实体,它们都是“群体”,差别很小。我想将其建模为单个连接,但不确定如何实现: # simplified for example interface Group { id: ID! type: String! } type WallGroup implements Node & Group { id: ID!

我正在关注阿波罗的连接、边缘、节点和中继概念。 我使用
节点{id:id!}
接口。我收集了各种各样的实体,它们都是“群体”,差别很小。我想将其建模为单个连接,但不确定如何实现:

     # simplified for example
    interface Group {
        id: ID!
        type: String!
    }
    type WallGroup implements Node & Group {
        id: ID!
        type: String!
    }
    type Event implements Node & Group {
        id: ID!
        type: String!
        dteStart: DateTime!
        dteEnd: DateTime!
    }
    type GroupEdge implements Edge {
        cursor: String!
        node: Group!
    }
    type GroupConnection implements Connection {
        edges: [GroupEdge!]!
        pageInfo: PageInfo!
        totalCount: Int!
    }
这将生成一个错误,因为
GroupEdge
希望节点成为
节点。是,但
接口不是,因此失败

我试过的另一件事是

    union AllGroup = WallGroup | Event
    type GroupEdge implements Edge {
        cursor: String!
        node: AllGroup!
    }
但这导致了同样的问题。显然,union失去了在
WallGroup
Event
上实现的节点接口的概念

有没有关于hwo的想法来对此进行建模,或者我应该复制所有内容?

只需要您的模式包含一个
节点
接口——在创建符合中继的接口时,通常不为连接和边缘创建接口

中继需要
节点
接口的原因是允许我们按id查询任何
节点
。但是,通常不需要返回多条边之一或多个连接之一的字段。因此,通常不需要为边或连接创建接口。这是您通常会做的:

interface Node {
  id: ID!
}

interface Group {
    id: ID!
    type: String!
}

type GroupA implements Node & Group {
    id: ID!
    type: String!
    # other fields
}

type GroupA implements Node & Group {
    id: ID!
    type: String!
    # other fields
}

type GroupEdge {
    cursor: String!
    node: Group!
}

type GroupConnection {
    edges: [GroupEdge!]!
    pageInfo: PageInfo!
    totalCount: Int!
}
根据“对于接口中定义的每个字段,[实现]对象类型必须包含一个同名字段。”因此,如果接口指定字段的类型为
Foo
,实现类型不能使字段的类型为
FooBar
,即使
Foo
是一个接口并且
FooBar
实现了它。不幸的是,这意味着不可能像您尝试的那样使用接口

如果您想利用接口提供各种安全网,并确保实现类型一致,您可以执行以下操作:

interface Connection {
  pageInfo: PageInfo!
  # don't specify edges
}

interface Edge {
  cursor: String!
  # don't specify node
}
通过这种方式,您可以确保像
pageInfo
cursor
这样的字段出现在实现类型中,具有正确的类型并且不为空。但这种模式级验证实际上是添加和实现这两个接口的唯一好处。

这只要求模式包含一个
节点
接口——在创建符合中继的接口时,通常不为连接和边缘创建接口

中继需要
节点
接口的原因是允许我们按id查询任何
节点
。但是,通常不需要返回多条边之一或多个连接之一的字段。因此,通常不需要为边或连接创建接口。这是您通常会做的:

interface Node {
  id: ID!
}

interface Group {
    id: ID!
    type: String!
}

type GroupA implements Node & Group {
    id: ID!
    type: String!
    # other fields
}

type GroupA implements Node & Group {
    id: ID!
    type: String!
    # other fields
}

type GroupEdge {
    cursor: String!
    node: Group!
}

type GroupConnection {
    edges: [GroupEdge!]!
    pageInfo: PageInfo!
    totalCount: Int!
}
根据“对于接口中定义的每个字段,[实现]对象类型必须包含一个同名字段。”因此,如果接口指定字段的类型为
Foo
,实现类型不能使字段的类型为
FooBar
,即使
Foo
是一个接口并且
FooBar
实现了它。不幸的是,这意味着不可能像您尝试的那样使用接口

如果您想利用接口提供各种安全网,并确保实现类型一致,您可以执行以下操作:

interface Connection {
  pageInfo: PageInfo!
  # don't specify edges
}

interface Edge {
  cursor: String!
  # don't specify node
}

通过这种方式,您可以确保像
pageInfo
cursor
这样的字段出现在实现类型中,具有正确的类型并且不为空。但是这种模式级验证实际上是添加和实现这两个接口的唯一好处。

我认为第一种方法是如何实现它的。这是错误:
接口字段Edge.node需要类型node!但是GroupEdge.node的类型为Group
接口连接{edges:[Edge!]!pageInfo:pageInfo!totalCount:Int!}
接口边缘{cursor:String!node:node!}
[抱歉,格式化此注释无效]该错误表示您仍在为边缘使用接口,所以我不相信你按照建议实现了它。我认为第一种方法是我如何实现它。这是错误:
接口字段Edge.node需要类型node!但是GroupEdge.node的类型为Group
接口连接{edges:[Edge!]!pageInfo:pageInfo!totalCount:Int!}
接口边缘{cursor:String!node:node!}
[抱歉,格式化此注释无效]该错误表明您仍在为边缘使用接口,因此我不相信您按照建议实现了它。