GraphQL - 如何区分公共字段和私有字段?

7
背景
我有一个GraphQL API和一个NodeJS & Angular应用程序,其中包含一个保存用户的MongoDB数据库。对于每个用户,都有一个公共页面,其中包含公共信息,如idusername。当用户登录时,会有一个私人配置文件页面,其中包含扩展信息,如email

仅作为背景说明,我使用jsonwebtokenaccesscontrol来验证和授权用户。该信息存储在每个GraphQL解析函数的上下文中,因此可以使用任何需要识别已登录用户所需的内容。

我有一个GraphQL查询,按以下方式检索公共用户:

query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

我正在思考如何正确实现检索公共或私人用户的方法。由于GraphQL是强类型的,我在寻找正确解决方案时遇到了一些困难。
问题: 如何区分公共用户和私人用户?
考虑因素:
1. 单独查询 因此,其中一个选项是为公共和私人字段分别设置单独的查询:
公共查询
query getUserById($id: ID!) {
  getUserById(id: $id) {
    id,
    username
  }
}

私有查询

query getMe {
  getMe {
    id,
    username,
    email
  }
}

2. 使用GraphQL接口
我看到了这篇介绍如何使用GraphQL接口的Medium文章,它解释了如何通过resolveType函数返回不同类型。所以我的做法是这样的:

query getUser($id: ID!) {
   getUser(id: $id) {
     ... on UserPrivate {
       id,
       username
     }
     ... on UserPublic {
       id,
       username,
       email
     }
   }
}

我还没有找到一个合适的解决方案,对于我目前拥有的任何一个想法我都不确定。

非常感谢任何帮助!

1个回答

12

我认为你在这里缺失的是,在GraphQL中通常需要创建这种深度连接的图形结构。虽然 getUserByIdgetMe 作为入口点效果很好(并且我认为它们即使在接口类型中仍然是一个好主意),但你很可能会在模式中遇到许多用户类型。想象一下流行的博客文章示例:

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

在这里添加两个作者字段并不是很有效。同样,在您的示例中,您可能不知道个人资料页面是自己的,直到从后端获得响应(考虑Twitter个人资料)。

我的建议是有两种方法可供考虑:

第一种是界面思想。您将拥有一个具有所有常见字段以及私有和公共类型的具体实现的接口。这里的好处是:如果只使用常见字段,则甚至无需使用类型匹配:

query getUser($id: ID!) {
   getUser(id: $id) {
     id
     username

     # if you need a private field you can branch off here
     ... on UserPrivate {
       email
     }
   }
}

当细粒度变得更高时(例如人们分享他们想展示给公众的内容,比如Facebook),或者你有很多类型(UserMe,UserFriend,UserStranger),你可能需要考虑使用可空字段。如果你无法访问该字段,则会从API中收到null。为了减少null检查的数量,你可以将字段轻松地捆绑到它们自己的类型中(例如

)。

总结:

从API的角度来看,返回可空字段会更容易一些,因为它给了你很大的灵活性。第二种选项比第一种更容易进化而不产生破坏性改变。如果在前端使用静态类型(Typescript、Flow、Scala.js、Reason等),使用接口更具表现力,也更有趣。关键词:模式匹配。


谢谢,这对我很有帮助 :) - Nicky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接