如果我有两种类型: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在其中查询email
字段User
对象即使用户没有请求也可以吗?
从what I see开始的代码方面,这就是我编写解析器的方式。每当用户请求obj.email
字段时,如何确保请求note
?
User: {
notes(obj, args, context, info) {
// How can I ensure obj.email is requested?
return NoteRetriever.getNotesByEmail(obj.email);
}
}
修改
我想知道,除非明确要求,否则父解析器不会解析email
字段。如果我们需要进行API调用以获取用户电子邮件该怎么办?因此,默认情况下,我们不要求它。但是,当请求备忘时,也可以请求电子邮件。
解析器是否可以指定对父字段的依赖关系-以确保得到请求?
答案 0 :(得分:1)
我认为期望是,如果您控制父级的查询,并期望子级中的值,则应确保所需的值始终由父级解析。
但是,有一种方法可以完成合并架构时的要求。 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 { ... }`));
请注意定义电子邮件字段的片段属性。在上面的链接中,它描述了如何解决此子项时如何强制给定字段在父项上进行解析。
答案 1 :(得分:0)
作为第一个参数传递给解析器的“父”值正是在父字段的解析器中返回的值(除非返回了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调用(如果未请求这些字段,则忽略其他),那么您需要修改该逻辑以解决{{ 1}}字段,需要notes
电子邮件。