深度大于 1 的嵌套解析器
Nested resolvers with depth greater than 1
问题
查看此 GraphQL 查询,
query {
asset {
name
interfaces {
created
ip_addresses {
value
network {
name
}
}
}
}
}
如何为 仅 ip_addresses 上的 network 字段定义解析器?
我的第一个想法
正在阅读docs单个嵌套查询的示例,例如
const resolverMap = {
Query: {
author(obj, args, context, info) {
return find(authors, { id: args.id });
},
},
Author: {
posts(author) {
return filter(posts, { authorId: author.id });
},
},
};
所以我想 - 为什么不将此模式应用于嵌套属性?
const resolverMap = {
Query: {
asset,
},
Asset: {
interfaces: {
ip_addresses: {
network: () => console.log('network resolver called'),
},
},
},
};
但这不起作用,当我 运行 查询时 - 我没有看到控制台日志。
进一步测试
我想确保解析器在查询 return 类型的根级别上始终被调用。
我的假设:
Asset: {
properties: () => console.log('properties - will be called'), // This will get called
interfaces: {
created: () => console.log('created - wont be called'),
ip_addresses: {
network_id: () => console.log('network - wont be called'),
},
},
},
果然我的控制台显示了
properties - will be called
令人困惑的部分
但是 apollo 仍然使用默认解析器来创建和 ip_addresses,正如我在 playground 中看到的 returned 数据。
解决方法
我可以按如下方式实现 "monolith" 解析器:
Asset: {
interfaces,
},
接口解析器执行如下操作的地方:
export const interfaces = ({ interfaces }) =>
interfaces.map(interfaceObj => ({ ...interfaceObj, ip_addresses: ip_addresses(interfaceObj) }));
export const ip_addresses = ({ ip_addresses }) =>
ip_addresses.map(ipAddressObj => ({
...ipAddressObj,
network: network(null, { id: ipAddressObj.network_id }),
}));
但我觉得这应该由默认解析器处理,因为这些自定义解析器实际上并没有做任何事情,而是将数据传递给另一个解析器。
传递给 ApolloServer
构造函数的解析器映射是一个对象,其中每个 属性 都是架构中 类型 的名称。这个属性的值是另一个对象,其中每个属性是那个类型的字段。然后,这些属性中的每一个都映射到该指定字段的解析器函数。
您在没有发布实际架构的情况下发布了查询,因此我们不知道您的任何类型实际命名的是什么,但假设 network
字段是 Network
,您的解析器映射需要类似于:
const resolver = {
// ... other types like Query, IPAddress, etc. as needed
Network: {
name: () => 'My network name'
}
}
当然,您可以为架构中的任何字段引入解析器。如果字段 return 是一个对象类型,您 return 一个 JavaScript 对象并且可以让默认解析器逻辑处理解析 "deeper" 字段:
const resolvers = {
IPAddress: {
network: () => {
return {
name: 'My network name',
}
}
}
}
或者...
const resolvers = {
Interface: {
ip_addresses: () => {
return [
{
value: 'Some value',
network: {
name: 'My network name',
},
},
]
}
}
}
您在何处覆盖默认解析器仅取决于从您的 root-level 字段中 return 编辑的数据在什么时候不再与您的架构匹配。有关默认解析器行为的更详细说明,请参阅 。
问题
查看此 GraphQL 查询,
query {
asset {
name
interfaces {
created
ip_addresses {
value
network {
name
}
}
}
}
}
如何为 仅 ip_addresses 上的 network 字段定义解析器?
我的第一个想法
正在阅读docs单个嵌套查询的示例,例如
const resolverMap = {
Query: {
author(obj, args, context, info) {
return find(authors, { id: args.id });
},
},
Author: {
posts(author) {
return filter(posts, { authorId: author.id });
},
},
};
所以我想 - 为什么不将此模式应用于嵌套属性?
const resolverMap = {
Query: {
asset,
},
Asset: {
interfaces: {
ip_addresses: {
network: () => console.log('network resolver called'),
},
},
},
};
但这不起作用,当我 运行 查询时 - 我没有看到控制台日志。
进一步测试
我想确保解析器在查询 return 类型的根级别上始终被调用。
我的假设:
Asset: {
properties: () => console.log('properties - will be called'), // This will get called
interfaces: {
created: () => console.log('created - wont be called'),
ip_addresses: {
network_id: () => console.log('network - wont be called'),
},
},
},
果然我的控制台显示了
properties - will be called
令人困惑的部分
但是 apollo 仍然使用默认解析器来创建和 ip_addresses,正如我在 playground 中看到的 returned 数据。
解决方法
我可以按如下方式实现 "monolith" 解析器:
Asset: {
interfaces,
},
接口解析器执行如下操作的地方:
export const interfaces = ({ interfaces }) =>
interfaces.map(interfaceObj => ({ ...interfaceObj, ip_addresses: ip_addresses(interfaceObj) }));
export const ip_addresses = ({ ip_addresses }) =>
ip_addresses.map(ipAddressObj => ({
...ipAddressObj,
network: network(null, { id: ipAddressObj.network_id }),
}));
但我觉得这应该由默认解析器处理,因为这些自定义解析器实际上并没有做任何事情,而是将数据传递给另一个解析器。
传递给 ApolloServer
构造函数的解析器映射是一个对象,其中每个 属性 都是架构中 类型 的名称。这个属性的值是另一个对象,其中每个属性是那个类型的字段。然后,这些属性中的每一个都映射到该指定字段的解析器函数。
您在没有发布实际架构的情况下发布了查询,因此我们不知道您的任何类型实际命名的是什么,但假设 network
字段是 Network
,您的解析器映射需要类似于:
const resolver = {
// ... other types like Query, IPAddress, etc. as needed
Network: {
name: () => 'My network name'
}
}
当然,您可以为架构中的任何字段引入解析器。如果字段 return 是一个对象类型,您 return 一个 JavaScript 对象并且可以让默认解析器逻辑处理解析 "deeper" 字段:
const resolvers = {
IPAddress: {
network: () => {
return {
name: 'My network name',
}
}
}
}
或者...
const resolvers = {
Interface: {
ip_addresses: () => {
return [
{
value: 'Some value',
network: {
name: 'My network name',
},
},
]
}
}
}
您在何处覆盖默认解析器仅取决于从您的 root-level 字段中 return 编辑的数据在什么时候不再与您的架构匹配。有关默认解析器行为的更详细说明,请参阅