GraphQL 解析器可以强制检索父级中的参数吗?
Posted
技术标签:
【中文标题】GraphQL 解析器可以强制检索父级中的参数吗?【英文标题】:Can a GraphQL resolver force arguments in parent to be retrieved? 【发布时间】:2019-08-15 22:35:01 【问题描述】:如果我有 2 种类型:User
和 Note
,具有以下架构:
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 解析器可以强制检索父级中的参数吗?的主要内容,如果未能解决你的问题,请参考以下文章
从 Iframe 调用父级中的 Fancybox,无需手动打开