GraphQL SDL 枚举类型

Posted

技术标签:

【中文标题】GraphQL SDL 枚举类型【英文标题】:GraphQL SDL enum types 【发布时间】:2019-01-07 07:26:26 【问题描述】:

我们在 SDL 中定义了一堆枚举类型,它们非常适合查询和突变。 在解析器部分,这些被映射到代表后端枚举的字符串。

例如在 SDL 中我们有:

enum WRRole 
    USER
    PROVIDER
    SUPPORT
    ADMIN
    SUPER_ADMIN
    GUEST

在解析器部分我们有:

WRRole: 
   USER: 'user',
   PROVIDER: 'provider',
   SUPPORT: 'support',
   ADMIN: 'admin',
   SUPER_ADMIN: 'super admin',
   GUEST: 'guest'
,

解析器使用 Mongoose 匹配 nodejs 后端中定义的枚举值,其中字段定义为:

...
roles: 
  type: [
    
      type: String,
      enum: ['user', 'provider', 'support', 'admin', 'super admin', 'guest']
    
  ],
  default: ['user']
,
...

我们对 GraphQL 枚举的问题是我们无法自省枚举并使用 GraphQL 自省取回映射......

这会导致构建 UI 时出现问题,我们希望在其中向用户显示这些选项的下拉列表。 SDL 枚举值(例如 SUPER_USER)非常适合键,但我们希望显示实际的后端映射值以供选择使用。

这只是我们拥有的众多枚举中的一个示例。许多映射值由多个单词组成,这些单词之间有空格或包含 SDL 枚举值中不允许的字符的单词,例如本例中的“super admin”。

所以我的问题是......你们如何处理这样的事情而不必重复自己或在前端添加更多代码以将这些映射到更有用的有意义的名称以进行演示????

不能保证顺序与后端枚举的定义顺序相匹配,因此添加到后端模型枚举会严重破坏 SUPER_USER 实际映射到“超级用户”的任何假设,即使解析器知道这一点。

问候

史蒂夫

【问题讨论】:

【参考方案1】:

虽然这个恕我直言没有完美的解决方案 我有几种方法可以解决这个问题

    优雅的方式 您可以将接收 Enum 名称的查询添加到您的 graphql 模式 像这样(在 SDL 中):

    type Query 
         getEnumValues(enumName: String!): [EnumKeyValue!]!
    
    
    type EnumKeyValue 
         key: String!
         value: String
    
    

    这需要您稍微更改后端代码,例如,我会更改 Enum 解析器以从如下对象获取数据:

    const enums = 
        WRRole: 
            USER: 'user',
            PROVIDER: 'provider',
            ...
        
    ;
    
    const enumResolver = 
        WRRole: 
           USER: enums.WRRole.USER,
           PROVIDER: enums.WRRole.PROVIDER,
           ...
        
    ;
    

    然后getEnumValues 的解析器将如下所示:

    const queryResolvers = 
          getEnumValues(source, args) 
               const enumKey = args.enumName;
    
               // enums is the same enums object from the previous example
               return Object.keys(enums[enumKey]).map(key => ( 
                    key,
                    value: enums[enumKey][key] 
               ))
    
          
    ;
    

    肮脏,辱骂但很快 另一种可能有点滥用的方法是在 Enum 值上添加描述 所以你的 Enum SDL 想:

        enum WRRole 
          # user
          USER
          # provider
          PROVIDER
          # support
          SUPPORT
          # admin
          ADMIN
          # super admin
          SUPER_ADMIN
          # guest
          GUEST
        
    

    然后您可以通过以下查询获得键和描述之间的映射:

        
          __type(name: "WRRole") 
            enumValues 
              description
              name
            
          
        
    

【讨论】:

有趣的是,我最初尝试了您的“肮脏、滥用但快速”的解决方案,但在这种情况下,描述的结果始终为空。 我目前正在研究另一种解决方案,因为我们有大量的枚举可供使用,因此您首选的解决方案过于复杂。 @user1790230 为什么结果为空? (你在使用模式拼接吗?)看看这个例子,应该可以工作launchpad.graphql.com/5507l37qw9我很想知道你还有什么其他的解决方案? 是的。我们将 4 个模式拼接在一起。其中两个是远程模式,另外两个是我们服务的本地模式。似乎没有保留枚举字段上的任何 cmets。所有其他类型的 cmets 都完好无损,这些都可以很好地自省。一旦我有一点时间,我将研究我想到的更通用的解决方案。这并不是说它会起作用,但不妨试一试,然后我会用答案更新这篇文章。 感谢丹尼尔提供的信息。我刚刚升级到 3.1.1,枚举上的 cmets 现在正在工作。这将为我节省很多精力,因此我已将您的答案标记为已接受。谢谢

以上是关于GraphQL SDL 枚举类型的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL 枚举类型会自动解析它们的值吗?

将枚举类型作为参数传递给 GraphQL 查询 - Quarkus

如何在 GraphQL 模式中定义嵌套枚举类型

如何将枚举类型字段从反应发送到 GraphQL/AWS appsync

如何使用 graphql-tools 使用或解析枚举类型?

在 Graphql 中使用枚举作为查询参数