【问题标题】:Enumerating all fields from a GraphQL query枚举 GraphQL 查询中的所有字段
【发布时间】:2018-08-17 11:38:59
【问题描述】:

给定 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 参数中。当您添加 unionsinline fragments 时,它会变得更加毛茸茸。

考虑到 GraphQL 的高级查询功能,有没有办法构建查询中请求的所有字段的集合?

有关info 参数的信息可以在on the Apollo docs sitegraphql-js Github repo 中找到。

【问题讨论】:

    标签: graphql apollo graphql-js apollo-server graphql-tools


    【解决方案1】:

    我知道这已经有一段时间了,但如果有人最终来到这里,Jake Pusareti 有一个名为 graphql-list-fields 的 npm 包可以做到这一点。它处理片段并跳过和包含指令。 您也可以查看代码here

    【讨论】:

      猜你喜欢
      • 2022-10-23
      • 2017-03-31
      • 2016-04-23
      • 2018-03-10
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      相关资源
      最近更新 更多