【问题标题】:Can a GraphQL resolver force arguments in parent to be retrieved?GraphQL 解析器可以强制检索父级中的参数吗?
【发布时间】: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 来获取用户的电子邮件怎么办?所以默认情况下我们不要求它。但是,在请求注释时,也可以请求电子邮件。

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

【问题讨论】:

    标签: graphql graphql-js


    【解决方案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% 正确的,它只能在缝合过程中发生,这是一个痛苦的开销
    猜你喜欢
    • 2018-10-21
    • 1970-01-01
    • 2021-12-09
    • 2018-07-01
    • 2021-03-12
    • 2021-04-01
    • 2019-07-14
    • 2022-01-03
    • 2020-09-26
    相关资源
    最近更新 更多