枚举 GraphQL 查询中的所有字段
Enumerating all fields from a GraphQL query
给定 Apollo Server 的 GraphQL 架构和解析器,以及 GraphQL 查询,是否有办法在解析器函数中创建所有请求字段(在对象或映射中)的集合?
对于简单的查询,很容易从解析器的 info
参数重新创建此集合。
给定一个架构:
type User {
id: Int!
username: String!
roles: [Role!]!
}
type Role {
id: Int!
name: String!
description: String
}
schema {
query: Query
}
type Query {
getUser(id: Int!): User!
}
和解析器:
Query: {
getUser: (root, args, context, info) => {
console.log(infoParser(info))
return db.Users.findOne({ id: args.id })
}
}
使用像这样的简单递归 infoParser
函数:
function infoParser (info) {
const fields = {}
info.fieldNodes.forEach(node => {
parseSelectionSet(node.selectionSet.selections, fields)
})
return fields
}
function parseSelectionSet (selections, fields) {
selections.forEach(selection => {
const name = selection.name.value
fields[name] = selection.selectionSet
? parseSelectionSet(selection.selectionSet.selections, {})
: true
})
return fields
}
此日志中的以下查询结果:
{
getUser(id: 1) {
id
username
roles {
name
}
}
}
=> { id: true, username: true, roles: { name: true } }
事情很快就会变得很糟糕,例如当您在查询中使用片段时:
fragment UserInfo on User {
id
username
roles {
name
}
}
{
getUser(id: 1) {
...UserInfo
username
roles {
description
}
}
}
GraphQL 引擎在执行时正确地忽略了重复、(深度)合并等查询字段,但它没有反映在 info
参数中。当您添加 unions and inline fragments 时,它只会变得更毛茸茸。
考虑到 GraphQL 的高级查询功能,是否有一种方法可以构建查询中请求的所有字段的集合?
可以找到关于 info
参数的信息 on the Apollo docs site and in the graphql-js Github repo。
我知道已经有一段时间了,但万一有人在这里结束,有一个名为 graphql-list-fields by Jake Pusareti 的 npm 包可以做到这一点。它处理片段并跳过和包含指令。
您还可以检查代码 here。
给定 Apollo Server 的 GraphQL 架构和解析器,以及 GraphQL 查询,是否有办法在解析器函数中创建所有请求字段(在对象或映射中)的集合?
对于简单的查询,很容易从解析器的 info
参数重新创建此集合。
给定一个架构:
type User {
id: Int!
username: String!
roles: [Role!]!
}
type Role {
id: Int!
name: String!
description: String
}
schema {
query: Query
}
type Query {
getUser(id: Int!): User!
}
和解析器:
Query: {
getUser: (root, args, context, info) => {
console.log(infoParser(info))
return db.Users.findOne({ id: args.id })
}
}
使用像这样的简单递归 infoParser
函数:
function infoParser (info) {
const fields = {}
info.fieldNodes.forEach(node => {
parseSelectionSet(node.selectionSet.selections, fields)
})
return fields
}
function parseSelectionSet (selections, fields) {
selections.forEach(selection => {
const name = selection.name.value
fields[name] = selection.selectionSet
? parseSelectionSet(selection.selectionSet.selections, {})
: true
})
return fields
}
此日志中的以下查询结果:
{
getUser(id: 1) {
id
username
roles {
name
}
}
}
=> { id: true, username: true, roles: { name: true } }
事情很快就会变得很糟糕,例如当您在查询中使用片段时:
fragment UserInfo on User {
id
username
roles {
name
}
}
{
getUser(id: 1) {
...UserInfo
username
roles {
description
}
}
}
GraphQL 引擎在执行时正确地忽略了重复、(深度)合并等查询字段,但它没有反映在 info
参数中。当您添加 unions and inline fragments 时,它只会变得更毛茸茸。
考虑到 GraphQL 的高级查询功能,是否有一种方法可以构建查询中请求的所有字段的集合?
可以找到关于 info
参数的信息 on the Apollo docs site and in the graphql-js Github repo。
我知道已经有一段时间了,但万一有人在这里结束,有一个名为 graphql-list-fields by Jake Pusareti 的 npm 包可以做到这一点。它处理片段并跳过和包含指令。 您还可以检查代码 here。