GraphQL 解析器可以强制检索父级中的参数吗?

Posted

技术标签:

【中文标题】GraphQL 解析器可以强制检索父级中的参数吗?【英文标题】:Can a GraphQL resolver force arguments in parent to be retrieved? 【发布时间】:2019-08-15 22:35:01 【问题描述】:

如果我有 2 种类型:UserNote,具有以下架构:

query 
   getUser(userId: ID!): User


type User 
   userId: ID
   email: String
   notes: [Note]


type Note 
   noteId: ID
   text: String

我正在为User#notes 编写解析器。现在说需要通过电子邮件地址检索笔记,所以我实际上需要将根对象传递给解析器以包含email 字段,无论如何我可以强制GraphQL 查询User 对象中的email 字段即使用户没有请求?

在代码方面,来自what I see,这就是我可以编写解析器的方式。每当用户请求note 字段时,如何确保请求obj.email

User:  
  notes(obj, args, context, info) 
    // How can I ensure obj.email is requested?
    return NoteRetriever.getNotesByEmail(obj.email);
  

编辑

我想知道父解析器不解析 email 字段的情况,除非明确要求。如果我们需要调用 API 来获取用户的电子邮件怎么办?所以默认情况下我们不要求它。但是,在请求注释时,也可以请求电子邮件。

有没有办法让解析器指定对父字段的依赖 - 以确保得到请求?

【问题讨论】:

【参考方案1】:

作为第一个参数传递给解析器的“父”值正是在父字段的解析器中返回的值(除非返回了 Promise,在这种情况下,它将是 Promise 解析为的任何内容)。因此,如果我们有这样的解析器:

Query: 
  getUser: () => 
    return 
      userId: 10,
      email: 'user@example.com',
      foobar: 42,
    
  

还有一个类似的查询:

query 
  getUser 
    id
    notes
  

传递给notes 解析器的是我们在解析器中为getUser 返回的整个对象。

User:  
  notes(obj, args, context, info) 
    console.log(obj.userId) // 10
    console.log(obj.email)  // "user@example.com"
    console.log(obj.foobar) // 42
  

无论请求的字段是什么,父值都是相同的,除非父字段解析器的逻辑实际上根据请求的字段返回不同的值。这意味着您还可以将任意数量的其他任意条目(如上面的 foobar)从父字段传递到每个子字段。

编辑:

字段彼此独立解析,因此没有声明字段之间依赖关系的机制。如果 getUser 解析器正在查看请求的字段并根据请求的字段进行某些 API 调用(如果未请求这些字段则省略其他字段),那么您需要修改该逻辑以考虑 notes 字段需要user 电子邮件。

【讨论】:

感谢您的回复。我想知道父解析器不解析电子邮件字段的情况,除非明确要求。如果我们需要调用 API 来获取用户的电子邮件怎么办?所以默认情况下我们不要求它。但是,当请求notes 时,也可以请求email 您需要在 getUser 解析器中处理该逻辑。查看我的编辑。【参考方案2】:

我认为期望是,如果您控制父级的查询,并期望子级中的值,则应确保所需的值始终由父级解析。

但是,有一种方法可以在合并模式时执行您所要求的操作。这在此处进行了描述https://www.apollographql.com/docs/graphql-tools/schema-stitching。

基本上需要有一个类似的基本架构

type Query 
    getUser(userId: ID!): User


type User 
   userId: ID
   email: String

使用与您现在相同的解析器,以及类似的第二个架构

type Note 
    noteId: ID
    text: String


extend type User 
    notes: [Note]

还有类似的东西

import  mergeSchemas  from 'graphql-tools';

const finalSchema = mergeSchemas(
    schemas: [userSchema, noteSchema],
    resolvers: 
        User 
            notes: 
                fragment: '... on User  email ',
                resolve: notesResolver
            
        
    
);
console.dir(await graphql(finalSchema, `query  ... `));

注意定义电子邮件字段的片段属性。在上面的链接中,它描述了当这个孩子被解析时,这将如何强制解析给定字段。

【讨论】:

感谢您的回复!我也遇到过这个。是的,这就是我想要的,但似乎只有在进行模式拼接时才会发生这种情况,而不是在普通的解析器定义中。 你是 100% 正确的,它只能在缝合过程中发生,这是一个痛苦的开销

以上是关于GraphQL 解析器可以强制检索父级中的参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

PHP在父级中访问子级的私有属性

父级中的Java方法占位符在子级中使用[重复]

从 Iframe 调用父级中的 Fancybox,无需手动打开

graphql-tools 突变解析器的参数不是 v > 0.8.0 中的对象?

在 iframe 父级中访问 div

在 iframe 父级中访问 div