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

问题描述 投票:0回答:5

我正在使用

graphql-tools
。收到 GraphQL 查询后,我使用 ElasticSearch 执行搜索并返回数据。

但是,通常请求的查询仅包含少数可能的字段,而不是全部。我只想将请求的字段传递给 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 graphql-js
5个回答
30
投票

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

来自 GraphQL 文档

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
可以是普通的字段选择、片段或内联片段。您必须合并所有这些才能了解在某个字段上选择的所有字段。


23
投票

有一个

info
对象作为解析器中的第四个参数传递。该参数包含您正在寻找的信息。

使用库作为

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']
    },
};

3
投票

根据 Herku 的回答:

对于给定的查询:

    query operationName($var: String!) {
      queryName(arg1: $var) {
        a
        b {
            c
        }
      }
    }

我能够获取解析器函数中的顶级字段。


// my resolver
{
  Query: {
    queryName: async (_, args, __, info) => {

      const topLevelFields = info.fieldNodes.reduce((all, currentNode) => {
        all.push(
          ...currentNode.selectionSet.selections.map(
            selection => {
              // or if selection.selectionSet is present, we can recursively get it's name.value, ('c' in this example)
              return selection.name.value;
            }
          )
        );
        return all;
      }, []);

      console.log(topLevelFields); // ['a','b']
    }
  }
}

2
投票

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
    ...

    }

事实上,您可能指的是前瞻数据获取。 上面的内容应该能让您对所请求的字段有足够的了解,您可以从中获取手动定制下游调用的信息。 但您也可以通过使用数据获取器寻找更有效的方法来实现此目的通过展望未来构建高效的数据获取器


0
投票

我构建了一个名为 graphql-lookahead 的库,它允许您通过传递

info
对象来仅获取请求的字段。

import { lookahead } from 'graphql-lookahead'

export const resolvers = {
  Query: {
    async user(_parent, _args, _context, info) {
      const requestedFields = []
      lookahead({ info, next: ({ field }) => requestedFields.push(field) })

      console.log(requestedFields)
      // => ['id', 'name', 'address']

      // or the object format from your question:
      const requestFieldObject = {}
      lookahead({ info, next: ({ field }) => (requestFieldObject[field] = '') })

      console.log(requestedFields)
      // => { id: '', name: '', address: '' }
    }
    // ...
  }
}

您可以通过迭代每个

selectionSet
info.fieldNodes
来自己完成此操作,但是当您有嵌套字段和片段时,它开始变得很难管理。

© www.soinside.com 2019 - 2024. All rights reserved.