gpt4 book ai didi

graphql - GraphQL 中具有一对多关系的多态性

转载 作者:行者123 更新时间:2023-12-02 16:27:33 27 4
gpt4 key购买 nike

我的架构中有以下实体。

  • 用户
  • 友情链接
  • 普通帖子

  • 我如何建模 User 之间的一对多关系和 Post类型 where Post可以是两种类型 LinkPostNormalPost .

    最佳答案

    我将使用 GraphQL 中存在的一种多态类型对这些模式进行建模。这种方法将为您在 future 的查询和扩展方面提供最大的灵活性。

    架构设计

    非常方便 User有一个 Posts 的数组像这样:

    type User {
    id: Int!
    email: String!
    posts: [Posts!]
    username: String!
    }

    这意味着 Post必须是 interfaceunion类型。这两种类型中的任何一种都允许我们利用 NormalPost 的事实。 & LinkedPost两者仍然是 Post 的类型.它还允许我们在同一个地方查询它们,就像在 user.posts 中一样。以上。

    接口(interface)

    interface type 的行为与 interface 的行为非常相似。在面向对象编程中。它定义了任何实现类型都必须具有的基本字段集。例如,所有 Post对象可能如下所示:
    interface Post {
    id: Int!
    author: String!
    dateCreated: String!
    dateUpdated: String!
    title: String!
    }

    任何类型 implements Post接口(interface)然后还必须有字段 id , author , dateCreated , dateUpdated & title除了特定于该类型的任何字段之外还实现了。所以使用 interface , NormalPost & LinkedPost可能如下所示:
    type NormalPost implements Post {
    id: Int!
    author: String!
    body: String!
    dateCreated: String!
    dateUpdated: String!
    title: String!
    }
    type LinkedPost implements Post {
    id: Int!
    author: String!
    dateCreated: String!
    dateUpdated: String!
    link: String!
    title: String!
    }

    工会

    union type 允许不需要实现相似字段的不同类型一起返回。 A union类型的结构与使用接口(interface)的方式不同,因为 union type 不指定任何字段。在 union 中定义的唯一内容模式定义是由 | 分隔的联合类型.

    该规则的唯一警告是 union 中的任何类型。定义了相同字段名称的字段需要具有相同的可空性(即,由于 NormalPost.title 不可为空( title: String! ),那么 LinkedPost.title 也必须不可为空。
    union Post = NormalPost | LinkedPost
    type NormalPost implements Post {
    id: Int!
    author: String!
    body: String!
    dateCreated: String!
    dateUpdated: String!
    title: String!
    }
    type LinkedPost implements Post {
    id: Int!
    author: String!
    dateCreated: String!
    dateUpdated: String!
    link: String!
    title: String!
    }

    查询

    以上介绍了如何区分 LinkedPost的问题来自 NormalPostuser.posts 查询它们时.在这两种情况下,您都需要使用条件 Fragment .

    条件片段允许从 interface 查询一组特定的字段。或 union类型。它们看起来与常规查询片段相同,因为它们是使用 ... on <Type> 定义的。查询正文中的语法。为 interface 构造条件片段的方式略有不同。对比 union类型。

    除了使用条件片段查询之外,添加 __typename 往往很有用。 Meta Field到您的多态查询,以便查询的使用者可以更好地识别代码中结果对象的类型。

    接口(interface)

    interface定义了一组特定的字段,所有实现类型都有这些字段可以像对类型的任何其他普通查询一样查询这些字段。不同的是当 interface类型具有特定于其类型的不同字段,例如 NormalPost.body对比 LinkedPost.link .选择整个 Post 的查询界面,然后是 NormalPost.bodyLinkedPost.link如下所示:
    query getUsersNormalAndLinkedPosts {
    user(id: 123) {
    id
    name
    username
    posts {
    __typename
    id
    author
    dateCreated
    dateUpdated
    title
    ... on NormalPost {
    body
    }
    ... on LinkedPost {
    link
    }
    }
    }
    }

    工会

    union不定义其类型之间的任何公共(public)字段,要选择的所有字段必须存在于每个条件片段中。这是查询 interface 的唯一区别和一个 union .查询 union类型如下:
    query getUsersNormalAndLinkedPosts {
    user(id: 123) {
    id
    name
    username
    posts {
    __typename
    ... on NormalPost {
    id
    author
    body
    dateCreated
    dateUpdated
    title
    }
    ... on LinkedPost {
    id
    author
    dateCreated
    dateUpdated
    link
    title
    }
    }
    }
    }

    结论

    两种多态类型都有优点和缺点,由您决定哪个最适合您的用例。我在构建 GraphQL 模式时使用了两者,以及使用时的具体差异 interfaceunion是在实现类型之间是否存在公共(public)字段。

    当实现类型之间的唯一区别只是一小组字段而其余字段在它们之间共享时,接口(interface)就很有意义。这会导致更小的查询和可能需要更少的条件片段。

    当您有一个类型作为多个不同类型的掩码时,联合真的很出色,这些类型不相关但又重新组合在一起,就像在一组搜索结果中一样。根据它返回的搜索类型,它可能会返回许多看起来完全不同的不同类型。例如,在 CMS 上进行的搜索可以同时产生用户和帖子。在这种情况下,具有以下类型是有意义的:
    union SearchResult = User | Post .

    然后可以从带有签名的查询中返回
    search(phrase: String!): [SearchResult!]

    在这个特定问题的上下文中,我会选择 interface从关系和查询的角度来看,它最有意义。

    关于graphql - GraphQL 中具有一对多关系的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54147366/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com