如何在 GraphQL 解析器中获取请求的字段?

How to get requested fields inside GraphQL resolver?

我正在使用 graphql-tools。收到 GraphQL 查询后,我使用 ElasticSearch 和 return 数据执行搜索。

但是,请求的查询通常只包括一些可能的字段,而不是全部。我只想将请求的字段传递给 ElasticSearch。 首先,我需要获取请求的字段。

我已经可以将整个查询作为字符串获取。例如,在解析器中,

const resolvers = {
  Query: {
    async user(p, args, context) {
      //can print  query as following
      console.log(context.query)                
    }
    .....
  }
}

打印为

query User { user(id:"111") { id  name address } }

有什么方法可以获取像

这样格式的请求字段
{ id:"",  name:"", address:"" }

在 graphql-js 解析器中公开了第四个参数,称为解析信息。该字段包含有关该字段的更多信息。

来自GraphQL docs GraphQLObjectType 配置参数类型定义:

// See below about resolver functions.
type GraphQLFieldResolveFn = (
  source?: any,
  args?: {[argName: string]: any},
  context?: any,
  info?: GraphQLResolveInfo
) => any

type GraphQLResolveInfo = {
  fieldName: string,
  fieldNodes: Array<Field>,
  returnType: GraphQLOutputType,
  parentType: GraphQLCompositeType,
  schema: GraphQLSchema,
  fragments: { [fragmentName: string]: FragmentDefinition },
  rootValue: any,
  operation: OperationDefinition,
  variableValues: { [variableName: string]: any },
}

fieldNodes 字段中,您可以搜索您的字段并获取特定字段的 selectionSet。从这里开始变得棘手,因为 selections 可以是普通字段选择、片段或内联片段。您必须合并所有这些才能知道在一个字段上选择的所有字段。

有一个 info 对象作为解析器中的第 4 个参数传递。此参数包含您要查找的信息。

使用库作为 graphql-fields 可以帮助您解析 graphql 查询数据:

const graphqlFields = require('graphql-fields');

const resolvers = {
  Query: {
    async user(_, args, context, info) {
      const topLevelFields = graphqlFields(info);
      console.log(Object.keys(topLevelFields)); // ['id', 'name', 'address']
    },
};

graphql-java 类似,您可以通过使用 myGetUsersResolverMethod(... DataFetchingEnvironment env) 扩展字段参数来执行相同的操作。

  • 这个 DataFetchingEnvironment 会为你注入,你可以遍历这个 DataFetchingEnvironment 对象作为 graph/查询的任何部分。

  • 此对象可让您更多地了解正在获取的内容以及已提供的参数。

示例:

    public List<User> getUsers(final UsersFilter filter, DataFetchingEnvironment env) {

    DataFetchingFieldSelectionSet selectionSet = env.getSelectionSet();
    selectionSet.getFields(); // <---List of selected fields
    selectionSet.getArguments(); // <--- Similarly but MAP
    ...

    }

事实上,您可能是在暗示前瞻性数据获取。上面的内容应该让您对请求的字段有足够的了解,您可以从那里获取它来手动定制下游调用。但是您也可以通过 using the data fetchers for Building efficient data fetchers by looking ahead

寻找更有效的方法来做到这一点